Skip to content

Commit 0d351ca

Browse files
committed
support fetching user insights reports
1 parent e83ad7a commit 0d351ca

9 files changed

Lines changed: 618 additions & 48 deletions

File tree

src/apis/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ pub fn urlencode<T: AsRef<str>>(s: T) -> String {
7272
pub mod access_token_service_api;
7373
pub mod api_key_service_api;
7474
pub mod auth_service_api;
75-
pub mod org_service_api;
76-
pub mod user_service_api;
7775
pub mod employee_service_api;
7876
pub mod mfa_service_api;
77+
pub mod org_service_api;
78+
pub(crate) mod report_service_api;
79+
pub mod user_service_api;
7980

8081
pub mod configuration;

src/apis/report_service_api.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* propelauth
3+
*
4+
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
5+
*
6+
* The version of the OpenAPI document: 0.1.0
7+
*
8+
* Generated by: https://openapi-generator.tech
9+
*/
10+
11+
use reqwest;
12+
13+
use super::{configuration, Error};
14+
use crate::apis::ResponseContent;
15+
use crate::models::reports::{
16+
FetchReportQuery, OrgReport, OrgReportType, UserReportPage, UserReportType,
17+
};
18+
use crate::propelauth::auth::AUTH_HOSTNAME_HEADER;
19+
20+
/// struct for typed errors of methods [`fetch_user_report`] or [`fetch_org_report`]
21+
#[derive(Debug, Clone, Serialize, Deserialize)]
22+
#[serde(untagged)]
23+
pub enum FetchReportRequestError {
24+
Status401(serde_json::Value),
25+
Status400(serde_json::Value),
26+
Status429(serde_json::Value),
27+
UnknownValue(serde_json::Value),
28+
}
29+
30+
pub(crate) async fn fetch_user_report(
31+
configuration: &configuration::Configuration,
32+
report_key: UserReportType,
33+
params: FetchReportQuery,
34+
) -> Result<UserReportPage, Error<FetchReportRequestError>> {
35+
let local_var_configuration = configuration;
36+
37+
let local_var_client = &local_var_configuration.client;
38+
39+
let local_var_uri_str = format!(
40+
"{}/api/backend/v1/user_report/{report_key}",
41+
local_var_configuration.base_path,
42+
report_key = report_key.as_str(),
43+
);
44+
let mut local_var_req_builder =
45+
local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
46+
47+
local_var_req_builder = local_var_req_builder.query(&params);
48+
49+
if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
50+
local_var_req_builder =
51+
local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
52+
}
53+
if let Some(ref local_var_token) = local_var_configuration.bearer_access_token {
54+
local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned());
55+
};
56+
local_var_req_builder = local_var_req_builder.header(
57+
AUTH_HOSTNAME_HEADER,
58+
local_var_configuration.auth_hostname.to_owned(),
59+
);
60+
61+
let local_var_req = local_var_req_builder.build()?;
62+
let local_var_resp = local_var_client.execute(local_var_req).await?;
63+
64+
let local_var_status = local_var_resp.status();
65+
let local_var_content = local_var_resp.text().await?;
66+
67+
if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
68+
serde_json::from_str(&local_var_content).map_err(Error::from)
69+
} else {
70+
let local_var_entity: Option<FetchReportRequestError> =
71+
serde_json::from_str(&local_var_content).ok();
72+
let local_var_error: crate::apis::ResponseContent<FetchReportRequestError> =
73+
ResponseContent {
74+
status: local_var_status,
75+
content: local_var_content,
76+
entity: local_var_entity,
77+
};
78+
Err(Error::ResponseError(local_var_error))
79+
}
80+
}
81+
82+
pub(crate) async fn fetch_org_report(
83+
configuration: &configuration::Configuration,
84+
report_key: OrgReportType,
85+
params: FetchReportQuery,
86+
) -> Result<OrgReport, Error<FetchReportRequestError>> {
87+
let local_var_configuration = configuration;
88+
89+
let local_var_client = &local_var_configuration.client;
90+
91+
let local_var_uri_str = format!(
92+
"{}/api/backend/v1/org_report/{report_key}",
93+
local_var_configuration.base_path,
94+
report_key = report_key.as_str(),
95+
);
96+
let mut local_var_req_builder =
97+
local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
98+
99+
local_var_req_builder = local_var_req_builder.query(&params);
100+
101+
if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
102+
local_var_req_builder =
103+
local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
104+
}
105+
if let Some(ref local_var_token) = local_var_configuration.bearer_access_token {
106+
local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned());
107+
};
108+
local_var_req_builder = local_var_req_builder.header(
109+
AUTH_HOSTNAME_HEADER,
110+
local_var_configuration.auth_hostname.to_owned(),
111+
);
112+
113+
let local_var_req = local_var_req_builder.build()?;
114+
let local_var_resp = local_var_client.execute(local_var_req).await?;
115+
116+
let local_var_status = local_var_resp.status();
117+
let local_var_content = local_var_resp.text().await?;
118+
119+
if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
120+
serde_json::from_str(&local_var_content).map_err(Error::from)
121+
} else {
122+
let local_var_entity: Option<FetchReportRequestError> =
123+
serde_json::from_str(&local_var_content).ok();
124+
let local_var_error: crate::apis::ResponseContent<FetchReportRequestError> =
125+
ResponseContent {
126+
status: local_var_status,
127+
content: local_var_content,
128+
entity: local_var_entity,
129+
};
130+
Err(Error::ResponseError(local_var_error))
131+
}
132+
}

src/models/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ pub mod user_ids_query;
8989
pub use self::user_ids_query::UserIdsQuery;
9090
pub mod user_in_org;
9191
pub use self::user_in_org::UserInOrg;
92+
pub mod reports;
9293
pub mod user_metadata;
9394
pub use self::user_metadata::UserMetadata;
9495
pub mod user_paged_response;

src/models/reports.rs

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
#[derive(Clone, Debug, PartialEq, Default)]
4+
pub struct ReportPagination {
5+
pub page_size: Option<i32>,
6+
pub page_number: Option<i32>,
7+
}
8+
9+
#[derive(Clone, Debug, PartialEq, Serialize)]
10+
pub(crate) struct FetchReportQuery {
11+
pub(crate) report_interval: ReportInterval,
12+
#[serde(skip_serializing_if = "Option::is_none")]
13+
pub(crate) page_size: Option<i32>,
14+
#[serde(skip_serializing_if = "Option::is_none")]
15+
pub(crate) page_number: Option<i32>,
16+
}
17+
18+
#[derive(Clone, Debug, PartialEq)]
19+
pub enum OrgReportType {
20+
Attrition,
21+
Growth,
22+
Reengagement,
23+
Churn,
24+
}
25+
26+
impl OrgReportType {
27+
pub fn as_str(&self) -> &'static str {
28+
match self {
29+
OrgReportType::Attrition => "attrition",
30+
OrgReportType::Growth => "growth",
31+
OrgReportType::Reengagement => "reengagement",
32+
OrgReportType::Churn => "churn",
33+
}
34+
}
35+
}
36+
37+
#[derive(Clone, Debug, PartialEq)]
38+
pub enum UserReportType {
39+
TopInviter,
40+
Champion,
41+
Reengagement,
42+
Churn,
43+
}
44+
45+
impl UserReportType {
46+
pub fn as_str(&self) -> &'static str {
47+
match self {
48+
UserReportType::TopInviter => "top_inviter",
49+
UserReportType::Champion => "champion",
50+
UserReportType::Reengagement => "reengagement",
51+
UserReportType::Churn => "churn",
52+
}
53+
}
54+
}
55+
56+
#[derive(Clone, Debug, PartialEq, Serialize)]
57+
#[serde(untagged)]
58+
pub(crate) enum ReportInterval {
59+
TopInviter(TopInviterReportInterval),
60+
Champion(ChampionReportInterval),
61+
Reengagement(ReengagementReportInterval),
62+
Churn(ChurnReportInterval),
63+
Attrition(AttritionReportInterval),
64+
Growth(GrowthReportInterval),
65+
}
66+
67+
#[derive(Clone, Debug, PartialEq, Serialize)]
68+
pub enum TopInviterReportInterval {
69+
#[serde(rename = "30")]
70+
ThirtyDays,
71+
#[serde(rename = "60")]
72+
SixtyDays,
73+
#[serde(rename = "90")]
74+
NinetyDays,
75+
}
76+
77+
#[derive(Clone, Debug, PartialEq, Serialize)]
78+
pub enum ChampionReportInterval {
79+
#[serde(rename = "30")]
80+
ThirtyDays,
81+
#[serde(rename = "60")]
82+
SixtyDays,
83+
#[serde(rename = "90")]
84+
NinetyDays,
85+
}
86+
87+
#[derive(Clone, Debug, PartialEq, Serialize)]
88+
pub enum ReengagementReportInterval {
89+
#[serde(rename = "Weekly")]
90+
Weekly,
91+
#[serde(rename = "Monthly")]
92+
Monthly,
93+
}
94+
95+
#[derive(Clone, Debug, PartialEq, Serialize)]
96+
pub enum ChurnReportInterval {
97+
#[serde(rename = "7")]
98+
SevenDays,
99+
#[serde(rename = "14")]
100+
FourteenDays,
101+
#[serde(rename = "30")]
102+
ThirtyDays,
103+
}
104+
105+
#[derive(Clone, Debug, PartialEq, Serialize)]
106+
pub enum AttritionReportInterval {
107+
#[serde(rename = "30")]
108+
ThirtyDays,
109+
#[serde(rename = "60")]
110+
SixtyDays,
111+
#[serde(rename = "90")]
112+
NinetyDays,
113+
}
114+
115+
#[derive(Clone, Debug, PartialEq, Serialize)]
116+
pub enum GrowthReportInterval {
117+
#[serde(rename = "30")]
118+
ThirtyDays,
119+
#[serde(rename = "60")]
120+
SixtyDays,
121+
#[serde(rename = "90")]
122+
NinetyDays,
123+
}
124+
125+
#[derive(Debug, Clone, Deserialize)]
126+
pub struct OrgReportRecord {
127+
pub id: String,
128+
pub report_id: String,
129+
pub org_id: String,
130+
pub name: String,
131+
pub num_users: i32,
132+
pub org_created_at: i64,
133+
pub extra_properties: Option<serde_json::Value>,
134+
}
135+
136+
#[derive(Deserialize)]
137+
pub struct OrgReport {
138+
pub org_reports: Vec<OrgReportRecord>,
139+
pub current_page: i64,
140+
pub total_count: i64,
141+
pub page_size: i64,
142+
pub has_more_results: bool,
143+
pub report_time: i64,
144+
}
145+
146+
#[derive(Debug, Clone, Deserialize)]
147+
pub struct UserReportRecord {
148+
pub id: String,
149+
pub report_id: String,
150+
pub user_id: String,
151+
pub user_created_at: i64,
152+
pub username: Option<String>,
153+
pub first_name: Option<String>,
154+
pub last_name: Option<String>,
155+
pub email: String,
156+
pub last_active_at: i64,
157+
pub org_data: serde_json::Value,
158+
pub extra_properties: Option<serde_json::Value>,
159+
}
160+
#[derive(Deserialize)]
161+
pub struct UserReportPage {
162+
pub user_reports: Vec<UserReportRecord>,
163+
pub current_page: i64,
164+
pub total_count: i64,
165+
pub page_size: i64,
166+
pub has_more_results: bool,
167+
pub report_time: i64,
168+
}

src/propelauth/auth.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ use crate::apis::configuration::Configuration;
55
use crate::models::AuthTokenVerificationMetadata;
66
use crate::propelauth::access_token::AccessTokenService;
77
use crate::propelauth::api_key::ApiKeyService;
8+
use crate::propelauth::employee::EmployeeService;
89
use crate::propelauth::errors::InitializationError;
910
use crate::propelauth::helpers::map_autogenerated_error;
1011
use crate::propelauth::mfa::MfaService;
1112
use crate::propelauth::options::{AuthOptions, AuthOptionsWithTokenVerification};
1213
use crate::propelauth::org::OrgService;
14+
use crate::propelauth::reports::ReportService;
1315
use crate::propelauth::token::TokenService;
1416
use crate::propelauth::user::UserService;
15-
use crate::propelauth::employee::EmployeeService;
1617

1718
static BACKEND_API_BASE_URL: &str = "https://propelauth-api.com";
1819
pub(crate) static AUTH_HOSTNAME_HEADER: &str = "X-Propelauth-url";
@@ -124,12 +125,19 @@ impl PropelAuth {
124125
}
125126
}
126127

127-
/// API requests related to employees.
128+
/// API requests related to mfa.
128129
pub fn mfa(&self) -> MfaService {
129130
MfaService {
130131
config: &self.config,
131132
}
132133
}
134+
135+
/// API requests related to reports.
136+
pub fn reports(&self) -> ReportService {
137+
ReportService {
138+
config: &self.config,
139+
}
140+
}
133141
}
134142

135143
fn validate_auth_url_extract_hostname(auth_url: &str) -> Result<String, InitializationError> {

src/propelauth/errors.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::models::{
22
BadCreateAccessTokenError, BadCreateMagicLinkRequest, BadCreateOrgRequest,
33
BadCreateUserRequest, BadFetchOrgQuery, BadFetchUsersByQuery, BadFetchUsersInOrgQuery,
4-
BadMigrateUserRequest, BadMigrateUserPasswordRequest, BadUpdateOrgRequest, BadUpdatePasswordRequest,
5-
BadUpdateUserEmailRequest, BadUpdateUserMetadataRequest,
4+
BadMigrateUserPasswordRequest, BadMigrateUserRequest, BadUpdateOrgRequest,
5+
BadUpdatePasswordRequest, BadUpdateUserEmailRequest, BadUpdateUserMetadataRequest,
66
};
77
use thiserror::Error;
88

@@ -462,7 +462,7 @@ pub enum VerifyStepUpGrantError {
462462

463463
#[derive(Error, Debug, PartialEq, Clone)]
464464
pub enum SendSmsCodeError {
465-
#[error("Invalid API Key")]
465+
#[error("Invalid API Key")]
466466
InvalidApiKey,
467467

468468
#[error("Rate limited by PropelAuth")]
@@ -511,3 +511,14 @@ pub enum VerifySmsChallengeError {
511511
UnexpectedException,
512512
}
513513

514+
#[derive(Error, Debug, PartialEq, Clone)]
515+
pub enum FetchReportError {
516+
#[error("Invalid API Key")]
517+
InvalidApiKey,
518+
519+
#[error("Rate limited by PropelAuth")]
520+
PropelAuthRateLimit,
521+
522+
#[error("Unexpected exception, please try again")]
523+
UnexpectedException,
524+
}

0 commit comments

Comments
 (0)