dialtone_common 0.1.0

Dialtone Common Code
Documentation
//! `pun` means Preferred Username
use crate::ap::ActorType;

/// Person actors really don't have a suffix, so it is an empty string.
pub const APPLICATION_PUN_SUFFIX: &str = "*a";
pub const GROUP_PUN_SUFFIX: &str = "*g";
pub const ORGANIZATION_PUN_SUFFIX: &str = "*o";
pub const PERSON_PUN_SUFFIX: &str = "";
pub const SERVICE_PUN_SUFFIX: &str = "*s";

/// Creates a Preferred User Name (PUN). Because PUNs appear in URLs and such without context
/// of their type, they are given a namespace based on their type. This namespace consists of
/// appending a type discriminator preceded by the asterisk character for all but person types.
pub fn create_preferred_user_name(base_name: &str, actor_type: &ActorType) -> String {
    let suffix = match actor_type {
        ActorType::Application => APPLICATION_PUN_SUFFIX,
        ActorType::Group => GROUP_PUN_SUFFIX,
        ActorType::Organization => ORGANIZATION_PUN_SUFFIX,
        ActorType::Person => PERSON_PUN_SUFFIX,
        ActorType::Service => SERVICE_PUN_SUFFIX,
    };
    format!("{}{}", base_name.to_lowercase(), suffix)
}

pub fn has_pun_suffix(name: &str) -> bool {
    name.ends_with(APPLICATION_PUN_SUFFIX)
        || name.ends_with(GROUP_PUN_SUFFIX)
        || name.ends_with(ORGANIZATION_PUN_SUFFIX)
        || name.ends_with(SERVICE_PUN_SUFFIX)
}

pub fn actor_type_from_pun(pun: &str) -> ActorType {
    if pun.ends_with(APPLICATION_PUN_SUFFIX) {
        ActorType::Application
    } else if pun.ends_with(GROUP_PUN_SUFFIX) {
        ActorType::Group
    } else if pun.ends_with(ORGANIZATION_PUN_SUFFIX) {
        ActorType::Organization
    } else if pun.ends_with(SERVICE_PUN_SUFFIX) {
        ActorType::Service
    } else {
        ActorType::Person
    }
}

pub fn is_valid_pun(name: &str, allow_reserved: bool) -> bool {
    if !allow_reserved && name.starts_with('_') {
        return false;
    }
    name.find(&[' ', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '='])
        .is_none()
        && !name.is_empty()
}

#[cfg(test)]
#[allow(non_snake_case)]
mod pun_tests {
    use super::*;

    #[test]
    fn GIVEN_base_name_WHEN_create_person_pun_THEN_no_suffix() {
        // GIVEN
        let base = "foo";

        // WHEN ... THEN
        assert_eq!("foo", create_preferred_user_name(base, &ActorType::Person));
    }

    #[test]
    fn GIVEN_base_name_WHEN_create_group_pun_THEN_suffix_is_g() {
        // GIVEN
        let base = "foo";

        // WHEN ... THEN
        assert_eq!("foo*g", create_preferred_user_name(base, &ActorType::Group));
        assert_eq!(
            "foo*s",
            create_preferred_user_name(base, &ActorType::Service)
        );
    }

    #[test]
    fn GIVEN_base_name_WHEN_create_service_pun_THEN_suffix_is_s() {
        // GIVEN
        let base = "foo";

        // WHEN ... THEN
        assert_eq!(
            "foo*s",
            create_preferred_user_name(base, &ActorType::Service)
        );
    }

    #[test]
    fn GIVEN_base_name_WHEN_create_application_pun_THEN_suffix_is_a() {
        // GIVEN
        let base = "foo";

        // WHEN ... THEN
        assert_eq!(
            "foo*a",
            create_preferred_user_name(base, &ActorType::Application)
        );
    }

    #[test]
    fn GIVEN_base_name_WHEN_create_organization_pun_THEN_suffix_is_o() {
        // GIVEN
        let base = "foo";

        // WHEN ... THEN
        assert_eq!(
            "foo*o",
            create_preferred_user_name(base, &ActorType::Organization)
        );
    }

    #[test]
    fn GIVEN_valid_pun_WHEN_testing_validity_THEN_return_true() {
        assert!(is_valid_pun("foo", false));
    }

    #[test]
    fn GIVEN_invalid_pun_WHEN_testing_validity_THEN_return_false() {
        assert!(!is_valid_pun("foo!", false));
    }

    #[test]
    fn GIVEN_valid_reserved_pun_WHEN_testing_validity_but_not_reserved_THEN_return_false() {
        assert!(!is_valid_pun("_foo", false));
    }

    #[test]
    fn GIVEN_valid_reserved_pun_WHEN_testing_validity_allowing_reserved_THEN_return_true() {
        assert!(is_valid_pun("_foo", true));
    }
}