- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 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
fn do_get_summary(req: &HttpRequest<AppState>) -> SummaryFuture {
let token = req.token().expect("ISE: token not verified during AuthMiddleware stage");
let datetime = req.match_info()
.get("timestamp")
.and_then(|s| i64::from_str(s).ok())
.map(|ts| NaiveDateTime::from_timestamp(ts, 0));
let datetime = match datetime {
Some(dt) => dt,
None => return Box::new(future::result(Err(ServiceError::InvalidSetting {
key: "timestamp".into(),
hint: "local time in seconds since Unix Epoch".into()
}.into())))
};
let db = req.state().db.clone();
let settings = req.state().db
.send(db::GetSettings(token.clone()))
.map_err(failure::Error::from)
// flatten error
.and_then(|res| match res {
Ok(settings) => Ok(settings),
Err(err) => Err(err)
});
let fitbit = req.state().db
.send(db::GetSettingsFitbit(token))
.map_err(failure::Error::from)
// Check if there is token and flatten error
.and_then(|res| match res {
Ok(fitbit) => {
if fitbit.client_token.is_none() {
Err(ServiceError::TokenExpired.into())
} else {
Ok(fitbit)
}
},
Err(err) => Err(err)
});
let headmaster = req.state().headmaster.clone();
let summary_and_token = settings.join(fitbit)
.and_then(move |(settings, fitbit)| -> Box<dyn Future<Item = (Summary, FitbitToken), Error = failure::Error>> {
// Deserialize token
let token = fitbit.client_token.expect("ISE: token option is not cleared");
let fitbit_token = match FitbitToken::from_json(&token) {
Ok(token) => token,
Err(err) => return Box::new(future::err(ServiceError::TokenExpired.into()))
};
let headmaster_config = master::HeadmasterConfig {
minimum_active_time: settings.hourly_activity_goal,
max_accounted_active_minutes: settings.hourly_activity_limit.unwrap_or(settings.hourly_activity_goal * 3),
debt_limit: settings.hourly_debt_limit.unwrap_or(settings.hourly_activity_goal * 3),
day_begins_at: settings.day_starts_at,
day_ends_at: settings.day_ends_at,
day_length: settings.day_length.unwrap_or((settings.day_ends_at.hour() - settings.day_starts_at.hour()) as i32),
user_date_time: datetime,
};
let auth_data = FitbitAuthData {
id: fitbit.client_id,
secret: fitbit.client_secret,
token: fitbit_token,
};
let future = headmaster.send(master::GetSummary::<FitbitActivityGrabber>::new(headmaster_config, auth_data))
.map_err(failure::Error::from)
// flatten error
.and_then(|res| res);
Box::new(future)
});
let summary = summary_and_token
.and_then(move |(summary, fitbit_token)| {
db.send(db::UpdateSettingsFitbit::new(
token, db::models::UpdateFitbitCredentials {
client_token: Some(Some(fitbit_token.to_json())),
..Default::default()
}))
.map_err(failure::Error::from)
.and_then(|_| Ok(summary))
});
Box::new(summary)
}