-// import Cookies from 'js-cookie';
-import { Err, None, Ok, Option, Result, Some } from "@sniptt/monads";
-import IsomorphicCookie from "isomorphic-cookie";
+import { isAuthPath } from "@utils/app";
+import { clearAuthCookie, isBrowser, setAuthCookie } from "@utils/browser";
+import * as cookie from "cookie";
import jwt_decode from "jwt-decode";
import { LoginResponse, MyUserInfo } from "lemmy-js-client";
-import { BehaviorSubject, Subject } from "rxjs";
-import { isHttps } from "../env";
-import { i18n } from "../i18next";
-import { isBrowser, toast } from "../utils";
+import { toast } from "../toast";
+import { I18NextService } from "./I18NextService";
interface Claims {
sub: number;
}
export class UserService {
- private static _instance: UserService;
- public myUserInfo: Option<MyUserInfo> = None;
- public jwtInfo: Option<JwtInfo> = None;
- public jwtSub: Subject<Option<JwtInfo>> = new Subject<Option<JwtInfo>>();
- public unreadInboxCountSub: BehaviorSubject<number> =
- new BehaviorSubject<number>(0);
- public unreadReportCountSub: BehaviorSubject<number> =
- new BehaviorSubject<number>(0);
- public unreadApplicationCountSub: BehaviorSubject<number> =
- new BehaviorSubject<number>(0);
+ static #instance: UserService;
+ public myUserInfo?: MyUserInfo;
+ public jwtInfo?: JwtInfo;
private constructor() {
- this.setJwtInfo();
+ this.#setJwtInfo();
}
- public login(res: LoginResponse) {
- let expires = new Date();
+ public login({
+ res,
+ showToast = true,
+ }: {
+ res: LoginResponse;
+ showToast?: boolean;
+ }) {
+ const expires = new Date();
expires.setDate(expires.getDate() + 365);
- IsomorphicCookie.save("jwt", res.jwt, { expires, secure: isHttps });
- console.log("jwt cookie set");
- this.setJwtInfo();
+
+ if (isBrowser() && res.jwt) {
+ showToast && toast(I18NextService.i18n.t("logged_in"));
+ setAuthCookie(res.jwt);
+ this.#setJwtInfo();
+ }
}
public logout() {
- this.jwtInfo = None;
- this.myUserInfo = None;
- this.jwtSub.next(this.jwtInfo);
- IsomorphicCookie.remove("jwt"); // TODO is sometimes unreliable for some reason
- document.cookie = "jwt=; Max-Age=0; path=/; domain=" + location.host;
- location.reload(); // TODO may not be necessary anymore
- console.log("Logged out.");
+ this.jwtInfo = undefined;
+ this.myUserInfo = undefined;
+
+ if (isBrowser()) {
+ clearAuthCookie();
+ }
+
+ if (isAuthPath(location.pathname)) {
+ location.replace("/");
+ } else {
+ location.reload();
+ }
}
- public auth(throwErr = true): Result<string, string> {
- // Can't use match to convert to result for some reason
- let jwt = this.jwtInfo.map(j => j.jwt);
- if (jwt.isSome()) {
- return Ok(jwt.unwrap());
+ public auth(throwErr = false): string | undefined {
+ const jwt = this.jwtInfo?.jwt;
+
+ if (jwt) {
+ return jwt;
} else {
- let msg = "No JWT cookie found";
+ const msg = "No JWT cookie found";
+
if (throwErr && isBrowser()) {
- console.log(msg);
- toast(i18n.t("not_logged_in"), "danger");
+ console.error(msg);
+ toast(I18NextService.i18n.t("not_logged_in"), "danger");
}
- return Err(msg);
+
+ return undefined;
+ // throw msg;
}
}
- private setJwtInfo() {
- let jwt = IsomorphicCookie.load("jwt");
+ #setJwtInfo() {
+ if (isBrowser()) {
+ const { jwt } = cookie.parse(document.cookie);
- if (jwt) {
- let jwtInfo: JwtInfo = { jwt, claims: jwt_decode(jwt) };
- this.jwtInfo = Some(jwtInfo);
- this.jwtSub.next(this.jwtInfo);
+ if (jwt) {
+ this.jwtInfo = { jwt, claims: jwt_decode(jwt) };
+ }
}
}
public static get Instance() {
- return this._instance || (this._instance = new this());
+ return this.#instance || (this.#instance = new this());
}
}