/*
 * Tapis Security API
 *
 * The Tapis Security API provides for management of Security Kernel (SK) role-based authorization and secrets resources.
 *
 * The version of the OpenAPI document: 1.8.2
 * Contact: cicsupport@tacc.utexas.edu
 * Generated by: https://openapi-generator.tech
 */

use super::{ContentType, Error, configuration};
use crate::{apis::ResponseContent, models};
use reqwest;
use serde::{Deserialize, Serialize, de::Error as _};

/// struct for typed errors of method [`add_child_role`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum AddChildRoleError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`add_role_permission`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum AddRolePermissionError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`create_role`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum CreateRoleError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`delete_role_by_name`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum DeleteRoleByNameError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_default_user_role`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetDefaultUserRoleError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_role_by_name`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetRoleByNameError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_role_names`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetRoleNamesError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_role_permissions`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetRolePermissionsError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`preview_path_prefix`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PreviewPathPrefixError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`remove_child_role`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RemoveChildRoleError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`remove_path_permission_from_all_roles`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RemovePathPermissionFromAllRolesError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`remove_permission_from_all_roles`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RemovePermissionFromAllRolesError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`remove_role_permission`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RemoveRolePermissionError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`replace_path_prefix`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ReplacePathPrefixError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`role_permits`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RolePermitsError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`update_role_description`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum UpdateRoleDescriptionError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`update_role_name`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum UpdateRoleNameError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`update_role_owner`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum UpdateRoleOwnerError {
    Status400(models::RespBasic),
    Status401(models::RespBasic),
    Status404(models::RespName),
    Status500(models::RespBasic),
    UnknownValue(serde_json::Value),
}

/// Add a child role to another role using a request body. If the child already exists, then the request has no effect and the change count returned is zero. Otherwise, the child is added and the change count is one. Supported only for roles of type *USER*.  The user@tenant identity specified in JWT is authorized to make this request only if that user is an administrator or if the user owns both the parent and child roles.
pub async fn add_child_role(
    configuration: &configuration::Configuration,
    req_add_child_role: models::ReqAddChildRole,
) -> Result<models::RespChangeCount, Error<AddChildRoleError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_req_add_child_role = req_add_child_role;

    let uri_str = format!("{}/security/role/addChild", configuration.base_path);
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_add_child_role);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespChangeCount`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespChangeCount`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<AddChildRoleError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Add a permission to an existing role using a request body. If the permission already exists, then the request has no effect and the change count returned is zero. Otherwise, the permission is added and the change count is one.  Permissions are case-sensitive strings that follow the format defined by Apache Shiro (https://shiro.apache.org/permissions.html). This format defines any number of colon-separated (:) parts, with the possible use of asterisks (*) as wildcards and commas (,) as aggregators. Here are two example permission strings:      system:MyTenant:read,write:system1     system:MyTenant:create,read,write,delete:*  See the Shiro documentation for further details. Note that the three reserved characters, [: * ,], cannot appear in the text of any part. It's the application's responsibility to escape those characters in a manner that is safe in the application's domain.  ### Extended Permissions Tapis extends Shiro permission checking with *path semantics*. Path semantics allows the last part of pre-configured permissions to be treated as hierarchical path names, such as the paths used in POSIX file systems. Currently, only permissions that start with *files:* have their last (5th) component configured with path semantics.  Path semantics treat the extended permission part as the root of the subtree to which the permission is applied recursively. Grantees assigned the permission will have the permission on the path itself and on all its children.  As an example, consider a role that's assigned the following permission:      files:iplantc.org:read:stampede2:/home/bud  Users granted the role have read permission on the following file system resources on stampede2:      /home/bud     /home/bud/     /home/bud/myfile     /home/bud/mydir/myfile  Those users, however, will not have access to /home.  When an extended permission part ends with a slash, such as /home/bud/, then that part is interpreted as a directory or, more generally, some type of container. In such cases, the permission applies to the children of the path and to the path as written with a slash. For instance, for the file permission path /home/bud/, the permission allows access to /home/bud/ and /home/bud/myfile, but not to /home/bud.  When an extended permission part does not end with a slash, such as /home/bud, then the permission applies to the children of the path and to the path written with or without a trailing slash. For instance, for the file permission path /home/bud, the permission allows access to /home/bud, /home/bud/ and /home/bud/myfile.  In the previous examples, we assumed /home/bud was a directory. If /home/bud is a file (or more generally a leaf), then specifying the permission path /home/bud/ will not work as intended. Permissions with paths that have trailing slashes should only be used for directories, and they require a trailing slash whenever refering to the root directory. Permissions that don't have a trailing slash can represent directories or files, and thus are more general.  Extended permission checking avoids *false capture*. Whether a path has a trailing slash or not, permission checking will not capture similarly named sibling paths. For example, using the file permission path /home/bud, grantees are allowed access to /home/bud and all its children (if it's a directory), but not to the file /home/buddy.txt nor the directory /home/bud2.  For roles of type USER the request is authorized only if the requestor is the role owner, a tenant administrator or a site administrator. For roles of type TENANT_ADMIN the requestor must a tenant or site administrator. For roles of type RESTRICTED_SVC the requestor must a site administrator.
pub async fn add_role_permission(
    configuration: &configuration::Configuration,
    req_add_role_permission: models::ReqAddRolePermission,
) -> Result<models::RespChangeCount, Error<AddRolePermissionError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_req_add_role_permission = req_add_role_permission;

    let uri_str = format!("{}/security/role/addPerm", configuration.base_path);
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_add_role_permission);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespChangeCount`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespChangeCount`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<AddRolePermissionError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Create a role using a request body. Role names are case sensitive, alpha-numeric strings that can also contain underscores. Role names must start with an alphbetic character and can be no more than 58 characters in length. The desciption can be no more than 2048 characters long. If the role already exists, this request has no effect.  For the request to be authorized, the requestor must be either an administrator or a service allowed to perform updates in the new role's tenant.
pub async fn create_role(
    configuration: &configuration::Configuration,
    req_create_role: models::ReqCreateRole,
) -> Result<models::RespResourceUrl, Error<CreateRoleError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_req_create_role = req_create_role;

    let uri_str = format!("{}/security/role", configuration.base_path);
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_create_role);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespResourceUrl`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespResourceUrl`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<CreateRoleError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Delete the named role. A valid tenant and user must be specified as query parameters.  For roles of type USER the request is authorized only if the requestor is the role owner, a tenant administrator or a site administrator. For roles of type TENANT_ADMIN the requestor must a tenant or site administrator. For roles of type RESTRICTED_SVC the requestor must a site administrator.
pub async fn delete_role_by_name(
    configuration: &configuration::Configuration,
    role_name: &str,
    tenant: Option<&str>,
    role_type: Option<models::RoleTypeEnum>,
) -> Result<models::RespChangeCount, Error<DeleteRoleByNameError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_role_name = role_name;
    let p_query_tenant = tenant;
    let p_query_role_type = role_type;

    let uri_str = format!(
        "{}/security/role/{roleName}",
        configuration.base_path,
        roleName = crate::apis::urlencode(p_path_role_name)
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::DELETE, &uri_str);

    if let Some(ref param_value) = p_query_tenant {
        req_builder = req_builder.query(&[("tenant", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_role_type {
        req_builder = req_builder.query(&[("roleType", &serde_json::to_string(param_value)?)]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespChangeCount`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespChangeCount`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<DeleteRoleByNameError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Get a user's default role. The default role is implicitly created by the system when needed if it doesn't  already exist. No authorization required.  A user's default role is constructed by prepending '$$' to the user's name. This implies the maximum length of a user name is 58 since role names are limited to 60 characters.
pub async fn get_default_user_role(
    configuration: &configuration::Configuration,
    user: &str,
) -> Result<models::RespName, Error<GetDefaultUserRoleError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_user = user;

    let uri_str = format!(
        "{}/security/role/defaultRole/{user}",
        configuration.base_path,
        user = crate::apis::urlencode(p_path_user)
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespName`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespName`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetDefaultUserRoleError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Get the named role's definition. A valid tenant must be specified as a query parameter. This request is authorized if the requestor is a user that has access to the specified tenant or if the requestor is a service.
pub async fn get_role_by_name(
    configuration: &configuration::Configuration,
    role_name: &str,
    tenant: Option<&str>,
    role_type: Option<models::RoleTypeEnum>,
) -> Result<models::RespRole, Error<GetRoleByNameError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_role_name = role_name;
    let p_query_tenant = tenant;
    let p_query_role_type = role_type;

    let uri_str = format!(
        "{}/security/role/{roleName}",
        configuration.base_path,
        roleName = crate::apis::urlencode(p_path_role_name)
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_tenant {
        req_builder = req_builder.query(&[("tenant", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_role_type {
        req_builder = req_builder.query(&[("roleType", &serde_json::to_string(param_value)?)]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespRole`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespRole`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetRoleByNameError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Get the names of all roles in the tenant in alphabetic order. Future enhancements will include search filtering.  A valid tenant must be specified as a query parameter. This request is authorized if the requestor is a user that has access to the specified tenant or if the requestor is a service.
pub async fn get_role_names(
    configuration: &configuration::Configuration,
    tenant: Option<&str>,
    role_type: Option<models::RoleTypeEnum>,
) -> Result<models::RespNameArray, Error<GetRoleNamesError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_tenant = tenant;
    let p_query_role_type = role_type;

    let uri_str = format!("{}/security/role", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_tenant {
        req_builder = req_builder.query(&[("tenant", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_role_type {
        req_builder = req_builder.query(&[("roleType", &serde_json::to_string(param_value)?)]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespNameArray`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespNameArray`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetRoleNamesError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Get the named role's permissions. By default, all permissions assigned to the role, whether directly and transitively through child roles, are returned. Set the immediate query parameter to only retrieve permissions directly assigned to the role. A valid tenant must be specified.  This request is authorized if the requestor is a user that has access to the specified tenant or if the requestor is a service.
pub async fn get_role_permissions(
    configuration: &configuration::Configuration,
    role_name: &str,
    tenant: Option<&str>,
    immediate: Option<bool>,
) -> Result<models::RespNameArray, Error<GetRolePermissionsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_role_name = role_name;
    let p_query_tenant = tenant;
    let p_query_immediate = immediate;

    let uri_str = format!(
        "{}/security/role/{roleName}/perms",
        configuration.base_path,
        roleName = crate::apis::urlencode(p_path_role_name)
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_tenant {
        req_builder = req_builder.query(&[("tenant", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_immediate {
        req_builder = req_builder.query(&[("immediate", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespNameArray`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespNameArray`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetRolePermissionsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// This read-only endpoint previews the transformations that would take place if the same input was used on a  replacePathPrefix POST call. This call is also implemented as a POST so that the same input as used on replacePathPrefix can be used here, but this call changes nothing.  This endpoint can be used to get an accounting of existing system/path combinations that match the input specification. Such information is useful when trying to duplicate a set of permissions. For example, one may want to copy a file subtree to another location and assign the same permissions to the new subtree as currently exist on the original subtree. One could use  this call to calculate the users that should be granted permission on the new subtree.  The optional parameters are roleName, oldPrefix and newPrefix. No wildcards are defined for the path prefix parameters. When roleName is specified then only permissions assigned to that role are considered.  When the oldPrefix parameter is provided, it's used to filter out permissions whose paths do not begin with the specified string; when not provided, no path prefix filtering occurs.  When the newPrefix parameter is not provided no new characters are prepended to the new path, effectively just removing the oldPrefix from the new path. When neither oldPrefix nor newPrefix are provided, no path transformation occurs, though system IDs can still be transformed.  The result object contains an array of transformation objects, each of which contains the unique permission sequence number, the existing permission that matched the search criteria and the new permission if the specified transformations were applied.  A valid tenant and user must be specified in the request body. This request is authorized if the requestor is a user that has access to the specified tenant or if the requestor is a service.
pub async fn preview_path_prefix(
    configuration: &configuration::Configuration,
    req_preview_path_prefix: models::ReqPreviewPathPrefix,
) -> Result<models::RespPathPrefixes, Error<PreviewPathPrefixError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_req_preview_path_prefix = req_preview_path_prefix;

    let uri_str = format!(
        "{}/security/role/previewPathPrefix",
        configuration.base_path
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_preview_path_prefix);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespPathPrefixes`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespPathPrefixes`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<PreviewPathPrefixError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Remove a child role from a parent role using a request body. A valid tenant and user must be specified in the request body. Supported only for roles of type *USER*.  The user@tenant identity specified in JWT is authorized to make this request only if that user is an administrator or if they own the parent role.
pub async fn remove_child_role(
    configuration: &configuration::Configuration,
    req_remove_child_role: models::ReqRemoveChildRole,
) -> Result<models::RespChangeCount, Error<RemoveChildRoleError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_req_remove_child_role = req_remove_child_role;

    let uri_str = format!("{}/security/role/removeChild", configuration.base_path);
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_remove_child_role);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespChangeCount`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespChangeCount`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<RemoveChildRoleError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Remove an extended permission from all roles in a tenant using a request body. The tenant and permission must be specified in the request body.  Each role in the tenant is searched for the extended permission string and, where found, that permission is removed. The matching algorithm is string comparison with wildcard semantics on the path component. This is the same as an exact string match for all parts of the permission specification up to the path part. A match on the path part, however, occurs when its path is a prefix of a role permission's path. Consider the following permission specification:      files:mytenant:read:mysystem:/my/dir  which will match both of the following role permissions:      files:mytenant:read:mysystem:/my/dir/subdir/myfile     files:mytenant:read:mysystem:/my/dir33/yourfile  Note that a match to the second role permission might be a *false capture* if the intension was to remove all permissions to resources in the /my/dir subtree, but not those in other directories. To avoid this potential problem, callers can make two calls, one to this endpoint with a permSpec that ends with a slash (\"/\") and one to the removePermissionFromeAllRoles endpoint with no trailing slash. The former removes all children from the directory subtree, the latter removes the directory itself.  Only the Files service is authorized to make this call.
pub async fn remove_path_permission_from_all_roles(
    configuration: &configuration::Configuration,
    req_remove_permission_from_all_roles: models::ReqRemovePermissionFromAllRoles,
) -> Result<models::RespChangeCount, Error<RemovePathPermissionFromAllRolesError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_req_remove_permission_from_all_roles = req_remove_permission_from_all_roles;

    let uri_str = format!(
        "{}/security/role/removePathPermFromAllRoles",
        configuration.base_path
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_remove_permission_from_all_roles);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespChangeCount`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespChangeCount`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<RemovePathPermissionFromAllRolesError> =
            serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Remove a permission from all roles in a tenant using a request body. The tenant and permission must be specified in the request body.  Each role in the tenant is searched for the *exact* permission string and, where found, that permission is removed. The matching algorithm is simple, character by character, string comparison.  Permissions are not interpreted. For example, a permission that contains a wildcard (*) will only match a role's permission when the same wildcard is found in the exact same position. The same rule applies to permission segments with multiple, comma separated components: a match requires the exact same ordering and spacing of components.  Only services are authorized to make this call.
pub async fn remove_permission_from_all_roles(
    configuration: &configuration::Configuration,
    req_remove_permission_from_all_roles: models::ReqRemovePermissionFromAllRoles,
) -> Result<models::RespChangeCount, Error<RemovePermissionFromAllRolesError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_req_remove_permission_from_all_roles = req_remove_permission_from_all_roles;

    let uri_str = format!(
        "{}/security/role/removePermFromAllRoles",
        configuration.base_path
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_remove_permission_from_all_roles);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespChangeCount`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespChangeCount`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<RemovePermissionFromAllRolesError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Remove a permission from a role using a request body. A valid role, roleTenant and permission must be specified in the request body.  For roles of type USER the request is authorized only if the requestor is the role owner, a tenant administrator or a site administrator. For roles of type TENANT_ADMIN the requestor must a tenant or site administrator. For roles of type RESTRICTED_SVC the requestor must a site administrator.
pub async fn remove_role_permission(
    configuration: &configuration::Configuration,
    req_remove_role_permission: models::ReqRemoveRolePermission,
) -> Result<models::RespChangeCount, Error<RemoveRolePermissionError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_req_remove_role_permission = req_remove_role_permission;

    let uri_str = format!("{}/security/role/removePerm", configuration.base_path);
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_remove_role_permission);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespChangeCount`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespChangeCount`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<RemoveRolePermissionError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Replace the text in a permission specification when its last component defines an *extended path attribute*. Extended path attributes enhance the standard Shiro matching algorithm with one that treats designated components in a permission specification as a path name, such as a posix file or directory path name. This request is useful when files or directories have been renamed or moved and their authorizations need to be adjusted. Consider, for example, permissions that conform to the following specification:        files:tenantId:op:systemId:path  By definition, the last component is an extended path attribute whose content can be changed by replacePathPrefix requests. Specifically, paths that begin with the oldPrefix will have that prefix replaced with the newPrefix value. Replacement only occurs on permissions that also match the schema and oldSystemId parameter values. The systemId attribute is required to immediately precede the path attribute, which must be the last attribute.  Additionally, the oldSystemId is replaced with the newSystemId when a match is found. If a roleName is provided, then replacement is limited to permissions defined only in that role. Otherwise, permissions in all roles that meet the other matching criteria will be considered.  The optional parameters are roleName, oldPrefix and newPrefix. No wildcards are defined for the path prefix parameters. When roleName is specified then only permissions assigned to that role are considered.  When the oldPrefix parameter is provided, it's used to filter out permissions whose paths do not begin with the specified string; when not provided, no path prefix filtering occurs.  When the newPrefix parameter is not provided no new characters are prepended to the new path, effectively just removing the oldPrefix from the new path. When neither oldPrefix nor newPrefix are provided, no path transformation occurs, though system IDs can still be transformed.  The previewPathPrefix request provides a way to do a dry run using the same input as this request. The preview call calculates the permissions that would change and what their new values would be, but it does not actually change those permissions as replacePathPrefix does.  The input parameters are passed in the payload of this request. The response indicates the number of changed permission specifications.  The path prefix replacement operation is authorized if the user@tenant in the JWT represents a tenant administrator or the Files service.
pub async fn replace_path_prefix(
    configuration: &configuration::Configuration,
    req_replace_path_prefix: models::ReqReplacePathPrefix,
) -> Result<models::RespChangeCount, Error<ReplacePathPrefixError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_req_replace_path_prefix = req_replace_path_prefix;

    let uri_str = format!(
        "{}/security/role/replacePathPrefix",
        configuration.base_path
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_replace_path_prefix);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespChangeCount`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespChangeCount`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<ReplacePathPrefixError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Check to see if the specified role allows the specified permission.  Any authenticated user may make this request.   
pub async fn role_permits(
    configuration: &configuration::Configuration,
    role_name: &str,
    req_role_permits: models::ReqRolePermits,
    immediate: Option<bool>,
) -> Result<models::RespAuthorized, Error<RolePermitsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_role_name = role_name;
    let p_body_req_role_permits = req_role_permits;
    let p_query_immediate = immediate;

    let uri_str = format!(
        "{}/security/role/{roleName}/permits",
        configuration.base_path,
        roleName = crate::apis::urlencode(p_path_role_name)
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref param_value) = p_query_immediate {
        req_builder = req_builder.query(&[("immediate", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_role_permits);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespAuthorized`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespAuthorized`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<RolePermitsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Update an existing role's decription using a request body. The size limit on a description is 2048 characters.  This request is authorized if the requestor is the role owner or an administrator.
pub async fn update_role_description(
    configuration: &configuration::Configuration,
    role_name: &str,
    req_update_role_description: models::ReqUpdateRoleDescription,
) -> Result<models::RespBasic, Error<UpdateRoleDescriptionError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_role_name = role_name;
    let p_body_req_update_role_description = req_update_role_description;

    let uri_str = format!(
        "{}/security/role/updateDesc/{roleName}",
        configuration.base_path,
        roleName = crate::apis::urlencode(p_path_role_name)
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_update_role_description);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespBasic`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespBasic`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<UpdateRoleDescriptionError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Update an existing role's name using a request body. Role names are case sensitive, alphanumeric strings that can contain underscores but must begin with an alphabetic character. The limit on role name is 58 characters.  This request is authorized if the requestor is the role owner or an administrator.
pub async fn update_role_name(
    configuration: &configuration::Configuration,
    role_name: &str,
    req_update_role_name: models::ReqUpdateRoleName,
) -> Result<models::RespBasic, Error<UpdateRoleNameError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_role_name = role_name;
    let p_body_req_update_role_name = req_update_role_name;

    let uri_str = format!(
        "{}/security/role/updateName/{roleName}",
        configuration.base_path,
        roleName = crate::apis::urlencode(p_path_role_name)
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_update_role_name);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespBasic`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespBasic`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<UpdateRoleNameError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Update an existing role's owner using a request body. Required parameters in the payload are the *roleTenant*, which is the tenant of named role, and *newOwner*, which is the user to which role ownership is being transferred. The *newTenant* payload parameter is optional and only needed when the new owner resides in a different tenant than that of the current owner.  This request is authorized if the requestor is the role owner or an administrator. If a new tenant is specified, then the requestor must also be allowed to act in the new tenant.
pub async fn update_role_owner(
    configuration: &configuration::Configuration,
    role_name: &str,
    req_update_role_owner: models::ReqUpdateRoleOwner,
) -> Result<models::RespBasic, Error<UpdateRoleOwnerError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_role_name = role_name;
    let p_body_req_update_role_owner = req_update_role_owner;

    let uri_str = format!(
        "{}/security/role/updateOwner/{roleName}",
        configuration.base_path,
        roleName = crate::apis::urlencode(p_path_role_name)
    );
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref apikey) = configuration.api_key {
        let key = apikey.key.clone();
        let value = match apikey.prefix {
            Some(ref prefix) => format!("{} {}", prefix, key),
            None => key,
        };
        req_builder = req_builder.header("X-Tapis-Token", value);
    };
    req_builder = req_builder.json(&p_body_req_update_role_owner);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => Err(Error::from(serde_json::Error::custom(
                "Received `text/plain` content type response that cannot be converted to `models::RespBasic`",
            ))),
            ContentType::Unsupported(unknown_type) => {
                Err(Error::from(serde_json::Error::custom(format!(
                    "Received `{unknown_type}` content type response that cannot be converted to `models::RespBasic`"
                ))))
            }
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<UpdateRoleOwnerError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}
