import { ROLES, API_ORIGIN } from '../constants.js'; import { fetcher } from '@cloudron/pankow'; const changeHandlers = {}; const KEYS = { AVATAR: 'avatar', // only returns a URI with cachebusting }; function notifyChange(key, value) { const listener = changeHandlers[key] || []; listener.forEach(h => h(value)); } // key is one of KEYS function onChange(key, handler) { if (typeof handler !== 'function') return; if (!changeHandlers[key]) changeHandlers[key] = []; changeHandlers[key].push(handler); } function create() { const accessToken = localStorage.token; // we use that currently only to generate the avatarUrl for the change handler let profileCached = null; return { name: 'ProfileModel', async logout() { // attempt to destroy oidc session in the spirit of true SSO // eslint-disable-next-line no-empty, no-unused-vars try { await fetcher.del(`${API_ORIGIN}/api/v1/profile/sessions`, null, { access_token: accessToken }); } catch (e) {} localStorage.removeItem('token'); window.location.href = '/'; }, async get() { let error, result; try { result = await fetcher.get(`${API_ORIGIN}/api/v1/profile`, { access_token: accessToken }); } catch (e) { error = e; } if (error || result.status !== 200) { console.error('Failed to get profile.', error || result.status); return []; } if (error || result.status !== 200) return [error || result]; result.body.isAtLeastUserManager = [ ROLES.OWNER, ROLES.ADMIN, ROLES.MAIL_MANAGER, ROLES.USER_MANAGER ].indexOf(result.body.role) !== -1; result.body.isAtLeastMailManager = [ ROLES.OWNER, ROLES.ADMIN, ROLES.MAIL_MANAGER ].indexOf(result.body.role) !== -1; result.body.isAtLeastAdmin = [ ROLES.OWNER, ROLES.ADMIN ].indexOf(result.body.role) !== -1; result.body.isAtLeastOwner = [ ROLES.OWNER ].indexOf(result.body.role) !== -1; result.body.backgroundImageUrl = result.body.hasBackgroundImage ? `${API_ORIGIN}/api/v1/profile/background_image?access_token=${accessToken}&bustcache=${Date.now()}` : ''; result.body.avatarUrl = `${API_ORIGIN}/api/v1/profile/avatar/${result.body.id}?ts=${Date.now()}`; profileCached = result.body; return [null, result.body]; }, async setPassword(password, newPassword) { let result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/password`, { password, newPassword }, { access_token: accessToken }); } catch (e) { return [e]; } if (result.status !== 204) return [result]; return [null]; }, async setDisplayName(displayName) { let error, result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/display_name`, { displayName }, { access_token: accessToken }); } catch (e) { error = e; } if (error) return error; if (result.status !== 204) return result; return null; }, async setEmail(email, password) { let result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/email`, { email, password }, { access_token: accessToken }); } catch (e) { return [e]; } if (result.status !== 204) return [result]; return [null]; }, async setFallbackEmail(fallbackEmail, password) { let result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/fallback_email`, { fallbackEmail, password }, { access_token: accessToken }); } catch (e) { return [e]; } if (result.status !== 204) return [result]; return [null]; }, async setLanguage(language) { let error, result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/language`, { language }, { access_token: accessToken }); } catch (e) { error = e; } if (error) return error; if (result.status !== 204) return result; return null; }, async setAvatar(file) { const fd = new FormData(); fd.append('avatar', file); let error, result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/avatar`, fd, { access_token: accessToken }); } catch (e) { error = e; } if (error) return error; if (result.status !== 202) return result; notifyChange(KEYS.AVATAR, `${API_ORIGIN}/api/v1/profile/avatar/${profileCached.id}?ts=${Date.now()}`); return null; }, async unsetAvatar() { let error, result; try { result = await fetcher.del(`${API_ORIGIN}/api/v1/profile/avatar`, null, { access_token: accessToken }); } catch (e) { error = e; } if (error) return error; if (result.status !== 204) return result; return null; }, async setBackgroundImage(file) { const fd = new FormData(); if (file) fd.append('backgroundImage', file); let error, result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/background_image`, fd, { access_token: accessToken }); } catch (e) { error = e; } if (error) return error; if (result.status !== 202) return result; return null; }, async sendPasswordReset(identifier) { let error, result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/auth/password_reset_request`, { identifier }, { access_token: accessToken }); } catch (e) { error = e; } if (error) return error; if (result.status !== 202) return result; return null; }, async setTwoFASecret() { let error, result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/twofactorauthentication_secret`, {}, { access_token: accessToken }); } catch (e) { error = e; } if (error || result.status !== 200) return [error || result]; return [null, result.body]; }, async enableTwoFA(totpToken) { let error, result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/twofactorauthentication_enable`, { totpToken }, { access_token: accessToken }); } catch (e) { error = e; } if (error || result.status !== 204) return [error || result]; return [null]; }, async disableTwoFA(password) { let result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/twofactorauthentication_disable`, { password }, { access_token: accessToken }); } catch (e) { return [e]; } if (result.status !== 204) return [result]; return [null]; }, async setNotificationConfig(notificationConfig) { let error, result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/notification_config`, { notificationConfig }, { access_token: accessToken }); } catch (e) { error = e; } if (error || result.status !== 204) return [error || result]; return [null, result.body]; }, async setupAccount(data) { let error, result; try { result = await fetcher.post(`${API_ORIGIN}/api/v1/auth/setup_account`, data); } catch (e) { error = e; } if (error || result.status !== 201) return [error || result]; return [null, result.body]; }, }; } export default { KEYS, onChange, create, };