gitlab 0.1810.0

Gitlab API client.
Documentation
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use chrono::{DateTime, Utc};
use derive_builder::Builder;

use crate::api::common::{NameOrId, SortOrder};
use crate::api::endpoint_prelude::*;
use crate::api::ParamValue;

/// Represents the state of a project access token.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProjectAccessTokenState {
    /// Active tokens.
    Active,
    /// Inactive tokens.
    Inactive,
}

impl ProjectAccessTokenState {
    fn as_str(self) -> &'static str {
        match self {
            ProjectAccessTokenState::Active => "active",
            ProjectAccessTokenState::Inactive => "inactive",
        }
    }
}

impl ParamValue<'static> for ProjectAccessTokenState {
    fn as_value(&self) -> Cow<'static, str> {
        self.as_str().into()
    }
}

/// Fields by which project access tokens can be ordered.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProjectAccessTokenOrderBy {
    /// Order by creation date.
    CreatedAt,
    /// Order by last usage date.
    LastUsedAt,
}

impl ProjectAccessTokenOrderBy {
    fn as_str(&self) -> &'static str {
        match self {
            ProjectAccessTokenOrderBy::CreatedAt => "created_at",
            ProjectAccessTokenOrderBy::LastUsedAt => "last_used_at",
        }
    }
}

impl ParamValue<'static> for ProjectAccessTokenOrderBy {
    fn as_value(&self) -> Cow<'static, str> {
        self.as_str().into()
    }
}

/// Get access tokens of a project.
#[derive(Debug, Builder, Clone)]
#[builder(setter(strip_option))]
pub struct ProjectAccessTokens<'a> {
    /// The project for which to list tokens.
    #[builder(setter(into))]
    project: NameOrId<'a>,
    /// Filter tokens created on or after this date.
    #[builder(default)]
    created_after: Option<DateTime<Utc>>,
    /// Filter tokens created on or before this date.
    #[builder(default)]
    created_before: Option<DateTime<Utc>>,
    /// Filter tokens last used on or after this date.
    #[builder(default)]
    last_used_after: Option<DateTime<Utc>>,
    /// Filter tokens last used on or before this date.
    #[builder(default)]
    last_used_before: Option<DateTime<Utc>>,
    /// Filter by revoked status.
    #[builder(default)]
    revoked: Option<bool>,
    /// Search query for token name.
    #[builder(setter(into), default)]
    search: Option<Cow<'a, str>>,
    /// Filter by token state.
    #[builder(default)]
    state: Option<ProjectAccessTokenState>,
    /// Filter by description of the token.
    #[builder(setter(into), default)]
    #[deprecated(
        since = "0.1802.1",
        note = "no such parameter for access token filtering"
    )]
    description: Option<Cow<'a, str>>,
    /// Order results by a specific field.
    #[builder(default)]
    order_by: Option<ProjectAccessTokenOrderBy>,
    /// Sort order for the results.
    #[builder(default)]
    sort: Option<SortOrder>,
}

impl<'a> ProjectAccessTokens<'a> {
    /// Create a builder for the endpoint.
    pub fn builder() -> ProjectAccessTokensBuilder<'a> {
        ProjectAccessTokensBuilder::default()
    }
}

impl Endpoint for ProjectAccessTokens<'_> {
    fn method(&self) -> Method {
        Method::GET
    }

    fn endpoint(&self) -> Cow<'static, str> {
        format!("projects/{}/access_tokens", self.project).into()
    }

    fn parameters(&self) -> QueryParams<'_> {
        let mut params = QueryParams::default();

        params
            .push_opt("created_after", self.created_after)
            .push_opt("created_before", self.created_before)
            .push_opt("last_used_after", self.last_used_after)
            .push_opt("last_used_before", self.last_used_before)
            .push_opt("revoked", self.revoked)
            .push_opt("search", self.search.as_ref())
            .push_opt("state", self.state)
            .push_opt("order_by", self.order_by)
            .push_opt("sort", self.sort);

        #[allow(deprecated)]
        {
            params.push_opt("description", self.description.as_ref());
        }

        params
    }
}

impl Pageable for ProjectAccessTokens<'_> {}

#[cfg(test)]
mod tests {
    use chrono::{DateTime, Utc};
    use http::Method;

    use crate::api::common::SortOrder;
    use crate::api::projects::access_tokens::{
        ProjectAccessTokenOrderBy, ProjectAccessTokenState, ProjectAccessTokens,
        ProjectAccessTokensBuilderError,
    };
    use crate::api::{self, Query};
    use crate::test::client::{ExpectedUrl, SingleTestClient};

    #[test]
    fn test_project_access_token_state_as_str() {
        let items = &[
            (ProjectAccessTokenState::Active, "active"),
            (ProjectAccessTokenState::Inactive, "inactive"),
        ];

        for (i, s) in items {
            assert_eq!(i.as_str(), *s);
        }
    }

    #[test]
    fn test_project_access_token_order_by_as_str() {
        let items = &[
            (ProjectAccessTokenOrderBy::CreatedAt, "created_at"),
            (ProjectAccessTokenOrderBy::LastUsedAt, "last_used_at"),
        ];

        for (i, s) in items {
            assert_eq!(i.as_str(), *s);
        }
    }

    #[test]
    fn project_is_required() {
        let err = ProjectAccessTokens::builder().build().unwrap_err();
        crate::test::assert_missing_field!(err, ProjectAccessTokensBuilderError, "project");
    }

    #[test]
    fn project_is_sufficient() {
        ProjectAccessTokens::builder().project(1).build().unwrap();
    }

    #[test]
    fn endpoint() {
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder().project(1).build().unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    fn endpoint_created_after() {
        let created_after_dt = DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z")
            .unwrap()
            .with_timezone(&Utc);
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("created_after", "2023-01-01T00:00:00Z")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .created_after(created_after_dt)
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    fn endpoint_created_before() {
        let created_before_dt = DateTime::parse_from_rfc3339("2023-12-31T23:59:59Z")
            .unwrap()
            .with_timezone(&Utc);
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("created_before", "2023-12-31T23:59:59Z")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .created_before(created_before_dt)
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    fn endpoint_last_used_after() {
        let last_used_after_dt = DateTime::parse_from_rfc3339("2024-01-01T00:00:00Z")
            .unwrap()
            .with_timezone(&Utc);
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("last_used_after", "2024-01-01T00:00:00Z")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .last_used_after(last_used_after_dt)
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    fn endpoint_last_used_before() {
        let last_used_before_dt = DateTime::parse_from_rfc3339("2024-03-01T00:00:00Z")
            .unwrap()
            .with_timezone(&Utc);
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("last_used_before", "2024-03-01T00:00:00Z")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .last_used_before(last_used_before_dt)
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    fn endpoint_revoked() {
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("revoked", "false")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .revoked(false)
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    fn endpoint_search() {
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("search", "token-search")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .search("token-search")
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    fn endpoint_state() {
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("state", "active")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .state(ProjectAccessTokenState::Active)
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    #[allow(deprecated)]
    fn endpoint_description() {
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("description", "token-description")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .description("token-description")
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    fn endpoint_order_by() {
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("order_by", "last_used_at")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .order_by(ProjectAccessTokenOrderBy::LastUsedAt)
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }

    #[test]
    fn endpoint_sort() {
        let endpoint = ExpectedUrl::builder()
            .method(Method::GET)
            .endpoint("projects/1/access_tokens")
            .add_query_params(&[("sort", "asc")])
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = ProjectAccessTokens::builder()
            .project(1)
            .sort(SortOrder::Ascending)
            .build()
            .unwrap();
        api::ignore(endpoint).query(&client).unwrap();
    }
}