]> Untitled Git - lemmy-ui.git/blob - src/shared/services/UserService.ts
Fix workaround for broken logout (#836)
[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 } 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 unreadInboxCountSub: BehaviorSubject<number> =
27     new BehaviorSubject<number>(0);
28   public unreadReportCountSub: BehaviorSubject<number> =
29     new BehaviorSubject<number>(0);
30   public unreadApplicationCountSub: BehaviorSubject<number> =
31     new BehaviorSubject<number>(0);
32
33   private constructor() {
34     this.setJwtInfo();
35   }
36
37   public login(res: LoginResponse) {
38     let expires = new Date();
39     expires.setDate(expires.getDate() + 365);
40     res.jwt.match({
41       some: jwt => {
42         toast(i18n.t("logged_in"));
43         IsomorphicCookie.save("jwt", jwt, { expires, secure: isHttps });
44         this.setJwtInfo();
45         location.reload();
46       },
47       none: void 0,
48     });
49   }
50
51   public logout() {
52     this.jwtInfo = None;
53     this.myUserInfo = None;
54     IsomorphicCookie.remove("jwt"); // TODO is sometimes unreliable for some reason
55     document.cookie = "jwt=; Max-Age=0; path=/; domain=" + location.hostname;
56     location.reload();
57   }
58
59   public auth(throwErr = true): Result<string, string> {
60     // Can't use match to convert to result for some reason
61     let jwt = this.jwtInfo.map(j => j.jwt);
62     if (jwt.isSome()) {
63       return Ok(jwt.unwrap());
64     } else {
65       let msg = "No JWT cookie found";
66       if (throwErr && isBrowser()) {
67         console.log(msg);
68         toast(i18n.t("not_logged_in"), "danger");
69       }
70       return Err(msg);
71     }
72   }
73
74   private setJwtInfo() {
75     let jwt = IsomorphicCookie.load("jwt");
76
77     if (jwt) {
78       let jwtInfo: JwtInfo = { jwt, claims: jwt_decode(jwt) };
79       this.jwtInfo = Some(jwtInfo);
80     }
81   }
82
83   public static get Instance() {
84     return this._instance || (this._instance = new this());
85   }
86 }