DocSpace-client/packages/shared/store/AuthStore.ts

499 lines
13 KiB
TypeScript

// (c) Copyright Ascensio System SIA 2009-2024
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/* eslint-disable no-console */
import { makeAutoObservable, runInAction } from "mobx";
import api from "../api";
import { setWithCredentialsStatus } from "../api/client";
import { loginWithTfaCode } from "../api/user";
import { getPortalTenantExtra } from "../api/portal";
import { TUser } from "../api/people/types";
import { TCapabilities, TThirdPartyProvider } from "../api/settings/types";
import { logout as logoutDesktop } from "../utils/desktop";
import {
frameCallEvent,
isAdmin,
isPublicRoom,
insertDataLayer,
} from "../utils/common";
import { getCookie, setCookie } from "../utils/cookie";
import { TTenantExtraRes } from "../api/portal/types";
import { TenantStatus } from "../enums";
import { COOKIE_EXPIRATION_YEAR, LANGUAGE } from "../constants";
import { Nullable, TI18n } from "../types";
import { UserStore } from "./UserStore";
import { CurrentTariffStatusStore } from "./CurrentTariffStatusStore";
import { CurrentQuotasStore } from "./CurrentQuotaStore";
import { SettingsStore } from "./SettingsStore";
class AuthStore {
private userStore: UserStore | null = null;
private currentQuotaStore: CurrentQuotasStore | null = null;
private currentTariffStatusStore: CurrentTariffStatusStore | null = null;
settingsStore: SettingsStore | null = null;
isLoading = false;
version: string = "";
providers: TThirdPartyProvider[] = [];
capabilities: Nullable<TCapabilities> = null;
isInit = false;
isLogout = false;
isUpdatingTariff = false;
tenantExtra: Nullable<TTenantExtraRes> = null;
skipRequest = false;
skipModules = false;
constructor(
userStoreConst: UserStore,
currentTariffStatusStoreConst: CurrentTariffStatusStore,
currentQuotaStoreConst: CurrentQuotasStore,
settingsStore: SettingsStore,
) {
this.userStore = userStoreConst;
this.currentTariffStatusStore = currentTariffStatusStoreConst;
this.currentQuotaStore = currentQuotaStoreConst;
this.settingsStore = settingsStore;
makeAutoObservable(this);
const { socketHelper } = this.settingsStore;
socketHelper.on("s:change-quota-used-value", ({ featureId, value }) => {
console.log(`[WS] change-quota-used-value ${featureId}:${value}`);
runInAction(() => {
this.currentQuotaStore?.updateQuotaUsedValue(featureId, value);
});
});
socketHelper.on("s:change-quota-feature-value", ({ featureId, value }) => {
console.log(`[WS] change-quota-feature-value ${featureId}:${value}`);
runInAction(() => {
if (featureId === "free") {
this.updateTariff();
return;
}
this.currentQuotaStore?.updateQuotaFeatureValue(featureId, value);
});
});
socketHelper.on("s:change-user-quota-used-value", (options) => {
console.log(`[WS] change-user-quota-used-value`, options);
runInAction(() => {
if (options.customQuotaFeature === "user_custom_quota") {
this.userStore?.updateUserQuota(
options.usedSpace,
options.quotaLimit,
);
return;
}
const { customQuotaFeature, ...updatableObject } = options;
this.currentQuotaStore?.updateTenantCustomQuota(updatableObject);
});
});
}
setIsUpdatingTariff = (isUpdatingTariff: boolean) => {
this.isUpdatingTariff = isUpdatingTariff;
};
updateTariff = async () => {
this.setIsUpdatingTariff(true);
await this.getTenantExtra();
await this.currentTariffStatusStore?.setPayerInfo();
this.setIsUpdatingTariff(false);
};
init = async (skipRequest?: boolean, i18n?: TI18n) => {
if (this.isInit) return;
this.isInit = true;
this.skipRequest = skipRequest ?? false;
await this.settingsStore?.init();
const requests = [];
const isPortalDeactivated = this.settingsStore?.isPortalDeactivate;
const isPortalRestore =
this.settingsStore?.tenantStatus === TenantStatus.PortalRestore;
if (
this.settingsStore?.isLoaded &&
this.settingsStore?.socketUrl &&
!isPublicRoom() &&
!isPortalDeactivated
) {
requests.push(
this.userStore?.init(i18n).then(() => {
if (!isPortalRestore) {
this.getTenantExtra();
}
}),
);
} else {
this.userStore?.setIsLoaded(true);
}
if (this.isAuthenticated && !skipRequest) {
if (!isPortalRestore && !isPortalDeactivated)
requests.push(this.settingsStore?.getAdditionalResources());
if (!this.settingsStore?.passwordSettings) {
if (!isPortalRestore && !isPortalDeactivated) {
requests.push(this.settingsStore?.getCompanyInfoSettings());
}
}
}
return Promise.all(requests).then(() => {
const user = this.userStore?.user;
if (user?.id) {
insertDataLayer(user.id);
}
if (
user &&
this.settingsStore?.standalone &&
!this.settingsStore?.wizardToken &&
this.isAuthenticated &&
user.isAdmin
) {
requests.push(this.settingsStore.getPortals());
}
});
};
get isEnterprise() {
this.currentTariffStatusStore?.setIsEnterprise(
this.tenantExtra?.enterprise || false,
);
return this.tenantExtra?.enterprise;
}
get isCommunity() {
return this.tenantExtra?.opensource;
}
getTenantExtra = async () => {
let refresh = false;
if (window.location.search === "?complete=true") {
window.history.replaceState({}, document.title, window.location.pathname);
refresh = true;
}
const result = await getPortalTenantExtra(refresh);
if (!result) return;
const { tariff, quota, ...tenantExtra } = result;
runInAction(() => {
this.tenantExtra = { ...tenantExtra };
});
this.currentQuotaStore?.setPortalQuotaValue(quota);
this.currentTariffStatusStore?.setPortalTariffValue(tariff);
};
setLanguage() {
if (this.userStore?.user?.cultureName) {
if (getCookie(LANGUAGE) !== this.userStore.user.cultureName)
setCookie(LANGUAGE, this.userStore.user.cultureName, {
"max-age": COOKIE_EXPIRATION_YEAR,
});
} else {
setCookie(LANGUAGE, this.settingsStore?.culture || "en-US", {
"max-age": COOKIE_EXPIRATION_YEAR,
});
}
}
get isLoaded() {
let success = false;
if (this.isAuthenticated) {
success =
(this.userStore?.isLoaded && this.settingsStore?.isLoaded) ?? false;
if (success) this.setLanguage();
} else {
success = this.settingsStore?.isLoaded ?? false;
}
return success;
}
get language() {
const lang =
(this.userStore?.user && this.userStore.user.cultureName) ||
this.settingsStore?.culture ||
"en";
this.currentTariffStatusStore?.setLanguage(lang);
return lang;
}
get languageBaseName() {
try {
const intl = new Intl.Locale(this.language);
return intl.minimize().baseName;
} catch {
return "en";
}
}
get isAdmin() {
const user = this.userStore?.user;
if (!user || !user.id) return false;
return isAdmin(user);
}
get isRoomAdmin() {
const user = this.userStore?.user;
if (!user) return false;
return (
!user.isAdmin && !user.isOwner && !user.isVisitor && !user.isCollaborator
);
}
// get isQuotaAvailable() {
// const user = this.userStore?.user;
// if (!user) return false;
// return user.isOwner || user.isAdmin || this.isRoomAdmin;
// }
get isPaymentPageAvailable() {
const user = this.userStore?.user;
if (!user) return false;
return user.isOwner || user.isAdmin;
}
get isTeamTrainingAlertAvailable() {
const user = this.userStore?.user;
if (!user) return false;
return (
!!this.settingsStore?.bookTrainingEmail &&
(user.isOwner || user.isAdmin || this.isRoomAdmin)
);
}
get isLiveChatAvailable() {
const user = this.userStore?.user;
if (!user) return false;
return (
!!this.settingsStore?.zendeskKey &&
(user.isOwner || user.isAdmin || this.isRoomAdmin)
);
}
login = async (user: TUser, hash: string, session = true) => {
try {
const response = (await api.user.login(user, hash, session)) as {
token: string;
tfa: string;
error: { message: unknown };
confirmUrl: string;
};
if (!response || (!response.token && !response.tfa))
throw response.error.message;
if (response.tfa && response.confirmUrl) {
const url = response.confirmUrl.replace(window.location.origin, "");
return await Promise.resolve({ url, user, hash });
}
setWithCredentialsStatus(true);
this.reset();
this.init();
return await Promise.resolve({ url: this.settingsStore?.defaultPage });
} catch (e) {
return Promise.reject(e);
}
};
loginWithCode = async (
userName: string,
passwordHash: string,
code: string,
) => {
await loginWithTfaCode(userName, passwordHash, code);
setWithCredentialsStatus(true);
this.reset();
this.init();
return Promise.resolve(this.settingsStore?.defaultPage);
};
thirdPartyLogin = async (SerializedProfile: string) => {
try {
const response = (await api.user.thirdPartyLogin(SerializedProfile)) as {
token: string;
};
if (!response || !response.token) throw new Error("Empty API response");
setWithCredentialsStatus(true);
this.reset();
this.init();
return await Promise.resolve(this.settingsStore?.defaultPage);
} catch (e) {
return Promise.reject(e);
}
};
reset = (skipUser = false) => {
this.isInit = false;
this.skipModules = false;
if (!skipUser) {
// this.userStore = new UserStore();
}
// this.settingsStore = new SettingsStore();
};
logout = async (reset = true) => {
const ssoLogoutUrl = await api.user.logout();
this.isLogout = true;
const isDesktop = this.settingsStore?.isDesktopClient;
const isFrame = this.settingsStore?.isFrame;
if (isDesktop) logoutDesktop();
if (isFrame) frameCallEvent({ event: "onSignOut" });
if (ssoLogoutUrl) return ssoLogoutUrl;
if (!reset) return;
setWithCredentialsStatus(false);
this.reset(true);
this.userStore?.setUser({} as TUser);
this.init();
};
get isAuthenticated() {
return (
this.settingsStore?.isLoaded &&
!!this.settingsStore?.socketUrl &&
!isPublicRoom()
// || //this.userStore.isAuthenticated
);
}
setDocumentTitle = (subTitle = null) => {
let title;
// const currentModule = this.settingsStore?.product;
const organizationName = this.settingsStore?.organizationName;
if (subTitle) {
title = `${subTitle} - ${organizationName}`;
// if (this.isAuthenticated && currentModule) {
// title = `${subTitle} - ${currentModule.title}`;
// } else {
// title = `${subTitle} - ${organizationName}`;
// }
// } else if ( organizationName) {
// title = `${currentModule.title} - ${organizationName}`;
} else {
title = organizationName;
}
document.title = title ?? "";
};
setProductVersion = (version: string) => {
this.version = version;
};
setProviders = (providers: TThirdPartyProvider[]) => {
this.providers = providers;
};
setCapabilities = (capabilities: TCapabilities) => {
this.capabilities = capabilities;
};
getAuthProviders = async () => {
const providers = await api.settings.getAuthProviders();
if (providers) this.setProviders(providers);
};
getCapabilities = async () => {
const capabilities = await api.settings.getCapabilities();
if (capabilities) this.setCapabilities(capabilities);
};
}
export { AuthStore };