logged_user.rs 3.1 KB

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