All files / src/utils LoginUtils.ts

94.11% Statements 32/34
69.23% Branches 9/13
100% Functions 5/5
93.93% Lines 31/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100                                                67x 4x 4x 4x               3x 2x 2x 2x     1x 1x 1x       1x 1x       67x 3x 3x 3x             1x       2x   3x 3x 3x 3x       67x 93x     67x   67x 3x 3x 3x 3x                            
import { ServerUrlLocalStorageKey, SERVER_URL } from '@config/base';
import { LanguageLocalStorageKey } from '@config/i18n';
import { clearTokens, getAccessToken, saveTokens } from "./TokenUtils";
 
interface Credentials {
  username: string,
  password: string,
  rememberMe: string
}
 
interface FetchJsonResponse<ResponseBody> {
  body: ResponseBody,
  response: Response
}
 
/**
 * Login user, <b>remember me is not implemented</b>,
 * Every request to backend has token in header for authentication.
 * username: username
 * password: password
 * rememberMe: whether to remember me, currently not implemented
 * @param credentials
 * @param sso
 */
const login = async (credentials: Credentials, sso = false): Promise<void | FetchJsonResponse<unknown>> => {
  const credentialsWithSso: RequestCredentials = sso? 'include' : 'same-origin';
  const body: BodyInit = sso? '' : JSON.stringify(credentials);
  const response = await fetch(`${SERVER_URL}/api/login`, {
    method: 'POST',
    body,
    headers: new Headers({
      'Content-Type': 'application/json'
    }),
    credentials: credentialsWithSso
  });
  if (response.ok) {
    const loginResult = await response.json();
    saveTokens(loginResult);
    return loginResult;
  } else {
    let info;
    try {
      const payload = await response.json();
      info = payload.info as { info: string; };
    } catch {
      info = 'Login failed';
    }
    console.error("Login failed, response: ", info);
    throw new Error(info as string);
  }
};
 
const logout = async (): Promise<void> => {
  try {
    const accessToken = getAccessToken();
    const response = await fetch(`${SERVER_URL}/api/logout`, {
      method: 'POST',
      headers: new Headers({
        'Authorization': "Bearer " + (accessToken == null ? "" : accessToken),
        'Content-Type': 'application/json'
      })
    });
    Iif (!response.ok) {
      console.error("Logout failed, response: ", response);
    }
  } catch (err) {
    console.error("Logout failed, response: ", err);
  }
  clearTokens();
  clearAllLocalStorage();
  setTimeout(() => {
    window.location.assign("/login");
  }, 500);
};
 
const loggedIn = (): boolean => {
  return getAccessToken() != null;
};
 
const preserveLocalStorageKeys = [ServerUrlLocalStorageKey, LanguageLocalStorageKey];
 
const clearAllLocalStorage = (): void => {
  const keys = Object.keys(localStorage);
  for (let i = 0; i < keys.length; i++) {
    Eif (!preserveLocalStorageKeys.includes(keys[i])) {
      localStorage.removeItem(keys[i]);
    }
  }
};
 
export {
  login,
  logout,
  loggedIn
};
 
export type {
  Credentials
};