logged_user.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. use crate::entities::token::{Claim, Token};
  2. use actix_web::http::HeaderValue;
  3. use backend_service::errors::ServerError;
  4. use chrono::{DateTime, Utc};
  5. use dashmap::DashMap;
  6. use lazy_static::lazy_static;
  7. lazy_static! {
  8. pub static ref AUTHORIZED_USERS: AuthorizedUsers = AuthorizedUsers::new();
  9. }
  10. #[derive(Debug, PartialEq, Eq, Hash, Clone)]
  11. pub struct LoggedUser {
  12. pub user_id: String,
  13. }
  14. impl std::convert::From<Claim> for LoggedUser {
  15. fn from(c: Claim) -> Self { Self { user_id: c.user_id() } }
  16. }
  17. impl LoggedUser {
  18. pub fn new(user_id: &str) -> Self {
  19. Self {
  20. user_id: user_id.to_owned(),
  21. }
  22. }
  23. pub fn from_token(token: String) -> Result<Self, ServerError> {
  24. let user: LoggedUser = Token::decode_token(&token.into())?.into();
  25. Ok(user)
  26. }
  27. pub fn as_uuid(&self) -> Result<uuid::Uuid, ServerError> {
  28. let id = uuid::Uuid::parse_str(&self.user_id)?;
  29. Ok(id)
  30. }
  31. }
  32. use actix_web::{dev::Payload, FromRequest, HttpRequest};
  33. use futures::future::{ready, Ready};
  34. impl FromRequest for LoggedUser {
  35. type Error = ServerError;
  36. type Future = Ready<Result<Self, Self::Error>>;
  37. fn from_request(request: &HttpRequest, _payload: &mut Payload) -> Self::Future {
  38. match Token::parser_from_request(request) {
  39. Ok(token) => ready(LoggedUser::from_token(token.0)),
  40. Err(err) => ready(Err(err)),
  41. }
  42. }
  43. }
  44. impl std::convert::TryFrom<&HeaderValue> for LoggedUser {
  45. type Error = ServerError;
  46. fn try_from(header: &HeaderValue) -> Result<Self, Self::Error> {
  47. match header.to_str() {
  48. Ok(val) => LoggedUser::from_token(val.to_owned()),
  49. Err(e) => {
  50. log::error!("Header to string failed: {:?}", e);
  51. Err(ServerError::unauthorized())
  52. },
  53. }
  54. }
  55. }
  56. #[derive(Clone, Debug, Copy)]
  57. enum AuthStatus {
  58. Authorized(DateTime<Utc>),
  59. NotAuthorized,
  60. }
  61. pub const EXPIRED_DURATION_DAYS: i64 = 30;
  62. pub struct AuthorizedUsers(DashMap<LoggedUser, AuthStatus>);
  63. impl AuthorizedUsers {
  64. pub fn new() -> Self { Self(DashMap::new()) }
  65. pub fn is_authorized(&self, user: &LoggedUser) -> bool {
  66. match self.0.get(user) {
  67. None => {
  68. tracing::debug!("user not login yet or server was reboot");
  69. false
  70. },
  71. Some(status) => match *status {
  72. AuthStatus::Authorized(last_time) => {
  73. let current_time = Utc::now();
  74. let days = (current_time - last_time).num_days();
  75. days < EXPIRED_DURATION_DAYS
  76. },
  77. AuthStatus::NotAuthorized => {
  78. tracing::debug!("user logout already");
  79. false
  80. },
  81. },
  82. }
  83. }
  84. pub fn store_auth(&self, user: LoggedUser, is_auth: bool) {
  85. let status = if is_auth {
  86. AuthStatus::Authorized(Utc::now())
  87. } else {
  88. AuthStatus::NotAuthorized
  89. };
  90. self.0.insert(user, status);
  91. }
  92. }