ts_control_serde/user.rs
1use chrono::{DateTime, Utc};
2use serde::Deserialize;
3use url::Url;
4
5/// A unique integer ID for a [`Login`]. This is not used by Tailscale node software, but is used
6/// in the control plane.
7pub type LoginId = i64;
8
9/// A unique integer ID for a [`User`].
10pub type UserId = i64;
11
12/// Represents a [`User`] from a specific identity provider (IdP), not associated with any
13/// particular Tailnet.
14#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
15#[serde(rename_all = "PascalCase")]
16pub struct Login<'a> {
17 /// The unique integer ID of this login. Unused on the Tailscale node-side, but used by the
18 /// control plane.
19 #[serde(rename = "ID")]
20 pub id: LoginId,
21 /// A string representation of the IdP itself, e.g. "google", "github", "okta_foo", etc.
22 #[serde(borrow)]
23 pub provider: &'a str,
24 /// An email address or "email-ish" string (e.g. "alice@github") associated with this Tailscale
25 /// user, according to the IdP.
26 #[serde(borrow)]
27 pub login_name: &'a str,
28 /// If populated, the display name of this Tailscale user, according to the IdP. Can be
29 /// overridden by a value in the [`User::display_name`] field.
30 #[serde(borrow, default)]
31 pub display_name: Option<&'a str>,
32 /// If populated, a URL to a profile picture representing this Tailscale user, according to the
33 /// IdP. Can be overridden by a value in the [`User::profile_pic_url`] field.
34 #[serde(
35 rename = "ProfilePicURL",
36 deserialize_with = "crate::util::deserialize_string_option",
37 default
38 )]
39 pub profile_pic_url: Option<Url>,
40}
41
42/// A Tailscale user.
43///
44/// A [`User`] can have multiple [`Login`]s associated with it (e.g. gmail and github oauth),
45/// although as of 2019, none of the UIs support this.
46///
47/// Some fields are inherited from the [`Login`]s and can be overridden, such as
48/// [`User::display_name`] and [`User::profile_pic_url`].
49#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
50#[serde(rename_all = "PascalCase")]
51pub struct User<'a> {
52 /// The unique integer ID of this Tailscale user.
53 #[serde(rename = "ID")]
54 pub id: UserId,
55 /// If populated, the display name of this Tailscale user. Overrides the value in any IdP-
56 /// provided [`Login::display_name`] field.
57 #[serde(borrow, default)]
58 pub display_name: Option<&'a str>,
59 /// If populated, a URL to a profile picture representing this Tailscale user. Overrides the
60 /// IdP-provided value in any [`Login::profile_pic_url`] field.
61 #[serde(
62 rename = "ProfilePicURL",
63 deserialize_with = "crate::util::deserialize_string_option",
64 default
65 )]
66 pub profile_pic_url: Option<Url>,
67 /// The date and time that this Tailscale user was created, in the UTC timezone.
68 #[serde(default)]
69 pub created: Option<DateTime<Utc>>,
70}
71
72/// Display-friendly data for a [`User`]. Includes the [`Login::login_name`] for display purposes.
73/// but *not* the [`Login::provider`]. Also includes derived data from one of the [`Login`]s
74/// associated with a [`User`].
75#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
76#[serde(rename_all = "PascalCase")]
77pub struct UserProfile<'a> {
78 /// The unique integer ID of this Tailscale user this [`UserProfile`] is associated with.
79 #[serde(rename = "ID")]
80 pub id: UserId,
81 /// An email address or "email-ish" string (e.g. "alice@github") associated with this Tailscale
82 /// user's [`UserProfile`], according to the IdP. For display purposes only.
83 #[serde(borrow, default)]
84 pub login_name: &'a str,
85 /// If populated, the display name of this Tailscale user (e.g. "Alice Smith"), according to
86 /// the IdP.
87 #[serde(borrow, default)]
88 pub display_name: Option<&'a str>,
89 /// If populated, a URL to a profile picture representing this Tailscale user.
90 #[serde(
91 rename = "ProfilePicURL",
92 deserialize_with = "crate::util::deserialize_string_option",
93 default
94 )]
95 pub profile_pic_url: Option<Url>,
96}