logged_user.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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 Config = ();
  36. type Error = ServerError;
  37. type Future = Ready<Result<Self, Self::Error>>;
  38. fn from_request(request: &HttpRequest, _payload: &mut Payload) -> Self::Future {
  39. match Token::parser_from_request(request) {
  40. Ok(token) => ready(LoggedUser::from_token(token.0)),
  41. Err(err) => ready(Err(err)),
  42. }
  43. }
  44. }
  45. impl std::convert::TryFrom<&HeaderValue> for LoggedUser {
  46. type Error = ServerError;
  47. fn try_from(header: &HeaderValue) -> Result<Self, Self::Error> {
  48. match header.to_str() {
  49. Ok(val) => LoggedUser::from_token(val.to_owned()),
  50. Err(e) => {
  51. log::error!("Header to string failed: {:?}", e);
  52. Err(ServerError::unauthorized())
  53. },
  54. }
  55. }
  56. }
  57. #[derive(Clone, Debug, Copy)]
  58. enum AuthStatus {
  59. Authorized(DateTime<Utc>),
  60. NotAuthorized,
  61. }
  62. pub const EXPIRED_DURATION_DAYS: i64 = 30;
  63. pub struct AuthorizedUsers(DashMap<LoggedUser, AuthStatus>);
  64. impl AuthorizedUsers {
  65. pub fn new() -> Self { Self(DashMap::new()) }
  66. pub fn is_authorized(&self, user: &LoggedUser) -> bool {
  67. match self.0.get(user) {
  68. None => {
  69. tracing::debug!("user not login yet or server was reboot");
  70. false
  71. },
  72. Some(status) => match *status {
  73. AuthStatus::Authorized(last_time) => {
  74. let current_time = Utc::now();
  75. let days = (current_time - last_time).num_days();
  76. days < EXPIRED_DURATION_DAYS
  77. },
  78. AuthStatus::NotAuthorized => {
  79. tracing::debug!("user logout already");
  80. false
  81. },
  82. },
  83. }
  84. }
  85. pub fn store_auth(&self, user: LoggedUser, is_auth: bool) {
  86. let status = if is_auth {
  87. AuthStatus::Authorized(Utc::now())
  88. } else {
  89. AuthStatus::NotAuthorized
  90. };
  91. self.0.insert(user, status);
  92. }
  93. }