1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use serde::{Deserialize, Serialize};
use sshkey_attest::proto::PublicKey as SshPublicKey;
use sshkeys::{KeyType, KeyTypeKind, PublicKeyKind};
use std::fmt;
use utoipa::ToSchema;
use uuid::Uuid;

use serde_with::skip_serializing_none;

use crate::constants::{ATTR_GROUP, ATTR_LDAP_SSHPUBLICKEY};

#[allow(dead_code)]
#[derive(ToSchema)]
#[schema(as = KeyTypeKind)]
pub struct KeyTypeKindSchema(KeyTypeKind);

#[derive(ToSchema)]
#[schema(as = KeyType)]
pub struct KeyTypeSchema {
    pub name: &'static str,
    pub short_name: &'static str,
    pub is_cert: bool,
    pub is_sk: bool,
    pub kind: KeyTypeKind,
    pub plain: &'static str,
}

#[allow(dead_code)]
#[derive(ToSchema)]
#[schema(as = PublicKeyKind)]
pub struct PublicKeyKindSchema(PublicKeyKind);

#[derive(ToSchema)]
#[schema(as = SshPublicKey)]
pub struct SshPublicKeySchema {
    pub key_type: KeyType,
    pub kind: PublicKeyKind,
    pub comment: Option<String>,
}

/// A token representing the details of a unix group
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct UnixGroupToken {
    pub name: String,
    pub spn: String,
    pub uuid: Uuid,
    pub gidnumber: u32,
}

impl fmt::Display for UnixGroupToken {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[ spn: {}, ", self.spn)?;
        write!(f, "gidnumber: {} ", self.gidnumber)?;
        write!(f, "name: {}, ", self.name)?;
        write!(f, "uuid: {} ]", self.uuid)
    }
}

/// Request addition of unix attributes to a group.
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct GroupUnixExtend {
    pub gidnumber: Option<u32>,
}

/// A token representing the details of a unix user
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct UnixUserToken {
    pub name: String,
    pub spn: String,
    pub displayname: String,
    pub gidnumber: u32,
    pub uuid: Uuid,
    pub shell: Option<String>,
    pub groups: Vec<UnixGroupToken>,
    pub sshkeys: Vec<SshPublicKey>,
    // The default value of bool is false.
    #[serde(default)]
    pub valid: bool,
}

impl fmt::Display for UnixUserToken {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "---")?;
        writeln!(f, "spn: {}", self.spn)?;
        writeln!(f, "name: {}", self.name)?;
        writeln!(f, "displayname: {}", self.displayname)?;
        writeln!(f, "uuid: {}", self.uuid)?;
        match &self.shell {
            Some(s) => writeln!(f, "shell: {}", s)?,
            None => writeln!(f, "shell: <none>")?,
        }
        self.sshkeys
            .iter()
            .try_for_each(|s| writeln!(f, "{}: {}", ATTR_LDAP_SSHPUBLICKEY, s))?;
        self.groups
            .iter()
            .try_for_each(|g| writeln!(f, "{}: {}", ATTR_GROUP, g))
    }
}

/// Request addition of unix attributes to an account
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct AccountUnixExtend {
    pub gidnumber: Option<u32>,
    // TODO: rename shell to loginshell everywhere we can find
    /// The internal attribute is "loginshell" but we use shell in the API currently
    #[serde(alias = "loginshell")]
    pub shell: Option<String>,
}