]> Untitled Git - lemmy-ui.git/blob - src/shared/services/UserService.ts
Adding option types 2 (#689)
[lemmy-ui.git] / src / shared / services / UserService.ts
1 // import Cookies from 'js-cookie';
2 import { Err, None, Ok, Option, Result, Some } from "@sniptt/monads";
3 import IsomorphicCookie from "isomorphic-cookie";
4 import jwt_decode from "jwt-decode";
5 import { LoginResponse, MyUserInfo } from "lemmy-js-client";
6 import { BehaviorSubject, Subject } from "rxjs";
7 import { isHttps } from "../env";
8 import { i18n } from "../i18next";
9 import { isBrowser, toast } from "../utils";
10
11 interface Claims {
12   sub: number;
13   iss: string;
14   iat: number;
15 }
16
17 interface JwtInfo {
18   claims: Claims;
19   jwt: string;
20 }
21
22 export class UserService {
23   private static _instance: UserService;
24   public myUserInfo: Option<MyUserInfo> = None;
25   public jwtInfo: Option<JwtInfo> = None;
26   public jwtSub: Subject<Option<JwtInfo>> = new Subject<Option<JwtInfo>>();
27   public unreadInboxCountSub: BehaviorSubject<number> =
28     new BehaviorSubject<number>(0);
29   public unreadReportCountSub: BehaviorSubject<number> =
30     new BehaviorSubject<number>(0);
31   public unreadApplicationCountSub: BehaviorSubject<number> =
32     new BehaviorSubject<number>(0);
33
34   private constructor() {
35     this.setJwtInfo();
36   }
37
38   public login(res: LoginResponse) {
39     let expires = new Date();
40     expires.setDate(expires.getDate() + 365);
41     IsomorphicCookie.save("jwt", res.jwt, { expires, secure: isHttps });
42     console.log("jwt cookie set");
43     this.setJwtInfo();
44   }
45
46   public logout() {
47     this.jwtInfo = None;
48     this.myUserInfo = None;
49     this.jwtSub.next(this.jwtInfo);
50     IsomorphicCookie.remove("jwt"); // TODO is sometimes unreliable for some reason
51     document.cookie = "jwt=; Max-Age=0; path=/; domain=" + location.host;
52     location.reload(); // TODO may not be necessary anymore
53     console.log("Logged out.");
54   }
55
56   public auth(throwErr = true): Result<string, string> {
57     // Can't use match to convert to result for some reason
58     let jwt = this.jwtInfo.map(j => j.jwt);
59     if (jwt.isSome()) {
60       return Ok(jwt.unwrap());
61     } else {
62       let msg = "No JWT cookie found";
63       if (throwErr && isBrowser()) {
64         console.log(msg);
65         toast(i18n.t("not_logged_in"), "danger");
66       }
67       return Err(msg);
68     }
69   }
70
71   private setJwtInfo() {
72     let jwt = IsomorphicCookie.load("jwt");
73
74     if (jwt) {
75       let jwtInfo: JwtInfo = { jwt, claims: jwt_decode(jwt) };
76       this.jwtInfo = Some(jwtInfo);
77       this.jwtSub.next(this.jwtInfo);
78     }
79   }
80
81   public static get Instance() {
82     return this._instance || (this._instance = new this());
83   }
84 }