pub struct Si { /* private fields */ }Expand description
SiServer API client with advanced session management.
This client handles the complex two-stage authentication flow required by SiServer and provides methods for report submission and calendar data retrieval. It implements resilient error handling to ensure application stability.
§Thread Safety
The client is not thread-safe due to mutable retry state. Each thread should use its own client instance for concurrent operations.
§Authentication Architecture
SiServer uses a sophisticated authentication system:
- LDAP Stage: Credentials sent to LDAP endpoint, token received
- Session Stage: Token sent to session endpoint, cookie received
- API Usage: Cookie included in all subsequent API requests
This design provides enhanced security but requires careful session management.
Implementations§
Source§impl Si
impl Si
Sourcepub fn new(config: &SiConfig) -> Self
pub fn new(config: &SiConfig) -> Self
Creates a new SiServer API client instance.
Initializes the HTTP client with default settings suitable for SiServer API interactions. The client is configured for both JSON and multipart requests to handle different SiServer endpoints appropriately.
§Arguments
config- SiServer configuration containing API endpoints and user information
§Examples
use kasl::api::si::{Si, SiConfig};
let config = SiConfig {
login: "username".to_string(),
auth_url: "https://auth.company.com".to_string(),
api_url: "https://api.company.com".to_string(),
};
let si = Si::new(&config);Sourcepub async fn send(&mut self, data: &str, date: &NaiveDate) -> Result<StatusCode>
pub async fn send(&mut self, data: &str, date: &NaiveDate) -> Result<StatusCode>
Submits a daily time tracking report to SiServer.
This method sends formatted daily report data to the SiServer API for payroll and time tracking integration. It handles session management and implements retry logic for authentication failures.
§Report Format
The report data should be a JSON string containing:
- Work hours and break information
- Task completion details
- Productivity metrics
- Any relevant metadata for the specified date
§Session Management
The method implements automatic session handling:
- Session Retrieval: Get or create a valid session token
- Report Submission: Send report data with session authentication
- Error Handling: Detect expired sessions and retry with re-authentication
- Status Return: Return HTTP status for caller handling
§Arguments
data- JSON string containing the formatted report datadate- The date for which the report is being submitted
§Returns
Returns the HTTP status code from the API response, allowing callers to determine success or specific failure modes.
§Errors
Returns an error if:
- Session management fails persistently
- Network request fails
- Request formatting fails
- Duration conversion fails (internal error)
§Examples
let mut si = Si::new(&config);
let report_data = r#"{"hours": 8, "tasks": 5}"#.to_string();
let today = Local::now().date_naive();
let status = si.send(&report_data, &today).await?;
if status.is_success() {
println!("Report submitted successfully");
}Sourcepub async fn send_monthly(&mut self, date: &NaiveDate) -> Result<StatusCode>
pub async fn send_monthly(&mut self, date: &NaiveDate) -> Result<StatusCode>
Submits a monthly summary report to SiServer.
Sends aggregated monthly statistics to the SiServer API for organizational reporting and payroll integration. The report covers the entire month containing the specified date.
§Monthly Report Contents
The system automatically generates a summary containing:
- Total working hours for the month
- Number of working days
- Average daily productivity
- Compliance with company policies
§Last Working Day Logic
Monthly reports are typically submitted on the last working day of each month. The system can automatically detect this condition and prompt for submission.
§Arguments
date- Any date within the target month for report generation
§Returns
Returns the HTTP status code from the API response.
§Examples
let mut si = Si::new(&config);
let today = Local::now().date_naive();
if si.is_last_working_day_of_month(&today)? {
let status = si.send_monthly(&today).await?;
if status.is_success() {
println!("Monthly report submitted");
}
}Sourcepub async fn rest_dates(
&mut self,
year: NaiveDate,
) -> Result<HashSet<NaiveDate>>
pub async fn rest_dates( &mut self, year: NaiveDate, ) -> Result<HashSet<NaiveDate>>
Fetches company rest dates and holidays for the specified year.
This method retrieves the official company calendar including holidays, vacation days, and extended weekend periods. The data is used for accurate productivity calculations and report generation.
§Error Resilience
This function prioritizes application stability over data completeness:
- Network errors return empty results rather than failing
- Authentication failures are logged but don’t interrupt operation
- API parsing errors result in empty calendar (graceful degradation)
- Session failures are handled with automatic retry
This design ensures that calendar integration enhances functionality without breaking core time tracking features when services are unavailable.
§Date Processing
The API returns three categories of rest dates:
- Regular holidays (national and company holidays)
- Vacation dates (company-specific rest periods)
- Weekend extensions (long weekend periods)
All categories are combined into a single set for unified processing.
§Arguments
year- Any date within the target year for calendar retrieval
§Returns
Returns a HashSet<NaiveDate> containing all rest dates for the year.
Returns an empty set on any error to ensure graceful degradation.
§Examples
let mut si = Si::new(&config);
let this_year = Local::now().date_naive();
let rest_dates = si.rest_dates(this_year).await?;
println!("Found {} rest dates this year", rest_dates.len());
// Check if a specific date is a rest day
let today = Local::now().date_naive();
if rest_dates.contains(&today) {
println!("Today is a company rest day");
}Sourcepub fn is_last_working_day_of_month(&self, date: &NaiveDate) -> Result<bool>
pub fn is_last_working_day_of_month(&self, date: &NaiveDate) -> Result<bool>
Determines if the specified date is the last working day of its month.
This utility function calculates whether a given date represents the final working day in its month, which is useful for triggering monthly report submissions and other end-of-month processing.
§Algorithm
The calculation process:
- Find Month End: Determine the last calendar day of the month
- Weekend Adjustment: Move backward from weekends to find working days
- Comparison: Check if the input date matches the calculated last working day
§Limitations
Currently only considers weekends (Saturday/Sunday) as non-working days. Future versions may integrate with the rest dates API to consider holidays and company-specific non-working days for more accurate calculations.
§Arguments
date- The date to check against the last working day
§Returns
Returns true if the date is the last working day of its month,
false otherwise.
§Errors
Currently cannot fail, but returns Result for consistency and
future enhancement with holiday integration.
§Examples
let si = Si::new(&config);
let date = NaiveDate::from_ymd_opt(2024, 1, 31).unwrap(); // January 31st
if si.is_last_working_day_of_month(&date)? {
println!("Time to submit monthly report!");
}Trait Implementations§
Source§impl Session for Si
impl Session for Si
Source§async fn login(&self) -> Result<String>
async fn login(&self) -> Result<String>
Performs two-stage authentication with SiServer.
This method implements SiServer’s unique authentication flow which requires two separate API calls to establish a session. The process is more complex than standard session authentication but provides enhanced security.
§Authentication Process
- LDAP Authentication: Send credentials to LDAP endpoint
- Token Extraction: Parse authentication token from response
- Session Exchange: Send token to session endpoint with Bearer auth
- Cookie Extraction: Parse session cookie from Set-Cookie header
- Format Preparation: Extract session ID for use in subsequent requests
§Error Scenarios
- LDAP authentication failure (invalid credentials)
- Token parsing failure (unexpected response format)
- Session exchange failure (token expired or invalid)
- Cookie extraction failure (missing or malformed Set-Cookie header)
§Returns
Returns the session ID string extracted from the PORTALSESSID cookie.
§Errors
Returns an error if:
- No credentials have been set (programming error)
- Network requests fail
- LDAP authentication fails
- Token or cookie parsing fails
- Authentication flow completes but no valid session is established
Source§fn set_credentials(&mut self, password: &str) -> Result<()>
fn set_credentials(&mut self, password: &str) -> Result<()>
Sets user credentials with SiServer-specific password encoding.
SiServer requires passwords to be double base64-encoded for security. This method handles the encoding and stores credentials in memory for use during the authentication process.
§Password Encoding
The password undergoes double base64 encoding:
- First encoding:
base64(password) - Second encoding:
base64(base64(password))
This provides additional security layers for credential transmission.
§Arguments
password- The user’s SiServer password in plain text
§Returns
Always returns Ok(()) as encoding cannot fail.
Source§fn session_id_file(&self) -> &str
fn session_id_file(&self) -> &str
Returns the filename for storing SiServer session tokens.
The session file is stored in the user’s application data directory and contains the cached session token for automatic login restoration.
Source§fn secret(&self) -> Secret
fn secret(&self) -> Secret
Returns a configured Secret instance for secure password prompting.
The Secret manager handles secure password input with hidden characters and optional encrypted caching in the user’s data directory.
§Returns
A configured Secret instance with SiServer-specific prompts and file names.
Source§fn retry(&self) -> i32
fn retry(&self) -> i32
Returns the current authentication retry count.
Used by the session management system to track failed authentication attempts and implement retry limits.
Source§fn inc_retry(&mut self)
fn inc_retry(&mut self)
Increments the authentication retry counter.
Called after each failed authentication attempt to track progress toward the maximum retry limit.
Source§fn reset_retry(&mut self)
fn reset_retry(&mut self)
Resets the authentication retry counter to zero.
Called after successful authentication to ensure future session requests start with a clean slate.