Run prettier
This commit is contained in:
@@ -1,429 +1,442 @@
|
||||
import {
|
||||
accountBillingPortalUrl,
|
||||
accountBillingSubscriptionUrl,
|
||||
accountPasswordUrl,
|
||||
accountPhoneUrl,
|
||||
accountPhoneVerifyUrl,
|
||||
accountReservationSingleUrl,
|
||||
accountReservationUrl,
|
||||
accountSettingsUrl,
|
||||
accountSubscriptionUrl,
|
||||
accountTokenUrl,
|
||||
accountUrl,
|
||||
maybeWithBearerAuth,
|
||||
tiersUrl,
|
||||
withBasicAuth,
|
||||
withBearerAuth
|
||||
accountBillingPortalUrl,
|
||||
accountBillingSubscriptionUrl,
|
||||
accountPasswordUrl,
|
||||
accountPhoneUrl,
|
||||
accountPhoneVerifyUrl,
|
||||
accountReservationSingleUrl,
|
||||
accountReservationUrl,
|
||||
accountSettingsUrl,
|
||||
accountSubscriptionUrl,
|
||||
accountTokenUrl,
|
||||
accountUrl,
|
||||
maybeWithBearerAuth,
|
||||
tiersUrl,
|
||||
withBasicAuth,
|
||||
withBearerAuth,
|
||||
} from "./utils";
|
||||
import session from "./Session";
|
||||
import subscriptionManager from "./SubscriptionManager";
|
||||
import i18n from "i18next";
|
||||
import prefs from "./Prefs";
|
||||
import routes from "../components/routes";
|
||||
import {fetchOrThrow, UnauthorizedError} from "./errors";
|
||||
import { fetchOrThrow, UnauthorizedError } from "./errors";
|
||||
|
||||
const delayMillis = 45000; // 45 seconds
|
||||
const intervalMillis = 900000; // 15 minutes
|
||||
|
||||
class AccountApi {
|
||||
constructor() {
|
||||
this.timer = null;
|
||||
this.listener = null; // Fired when account is fetched from remote
|
||||
this.tiers = null; // Cached
|
||||
}
|
||||
constructor() {
|
||||
this.timer = null;
|
||||
this.listener = null; // Fired when account is fetched from remote
|
||||
this.tiers = null; // Cached
|
||||
}
|
||||
|
||||
registerListener(listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
registerListener(listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
resetListener() {
|
||||
this.listener = null;
|
||||
}
|
||||
resetListener() {
|
||||
this.listener = null;
|
||||
}
|
||||
|
||||
async login(user) {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
console.log(`[AccountApi] Checking auth for ${url}`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBasicAuth({}, user.username, user.password)
|
||||
});
|
||||
const json = await response.json(); // May throw SyntaxError
|
||||
if (!json.token) {
|
||||
throw new Error(`Unexpected server response: Cannot find token`);
|
||||
async login(user) {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
console.log(`[AccountApi] Checking auth for ${url}`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBasicAuth({}, user.username, user.password),
|
||||
});
|
||||
const json = await response.json(); // May throw SyntaxError
|
||||
if (!json.token) {
|
||||
throw new Error(`Unexpected server response: Cannot find token`);
|
||||
}
|
||||
return json.token;
|
||||
}
|
||||
|
||||
async logout() {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
console.log(
|
||||
`[AccountApi] Logging out from ${url} using token ${session.token()}`
|
||||
);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
});
|
||||
}
|
||||
|
||||
async create(username, password) {
|
||||
const url = accountUrl(config.base_url);
|
||||
const body = JSON.stringify({
|
||||
username: username,
|
||||
password: password,
|
||||
});
|
||||
console.log(`[AccountApi] Creating user account ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
body: body,
|
||||
});
|
||||
}
|
||||
|
||||
async get() {
|
||||
const url = accountUrl(config.base_url);
|
||||
console.log(`[AccountApi] Fetching user account ${url}`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
headers: maybeWithBearerAuth({}, session.token()), // GET /v1/account endpoint can be called by anonymous
|
||||
});
|
||||
const account = await response.json(); // May throw SyntaxError
|
||||
console.log(`[AccountApi] Account`, account);
|
||||
if (this.listener) {
|
||||
this.listener(account);
|
||||
}
|
||||
return account;
|
||||
}
|
||||
|
||||
async delete(password) {
|
||||
const url = accountUrl(config.base_url);
|
||||
console.log(`[AccountApi] Deleting user account ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
password: password,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
async changePassword(currentPassword, newPassword) {
|
||||
const url = accountPasswordUrl(config.base_url);
|
||||
console.log(`[AccountApi] Changing account password ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
password: currentPassword,
|
||||
new_password: newPassword,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
async createToken(label, expires) {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
const body = {
|
||||
label: label,
|
||||
expires: expires > 0 ? Math.floor(Date.now() / 1000) + expires : 0,
|
||||
};
|
||||
console.log(`[AccountApi] Creating user access token ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
}
|
||||
|
||||
async updateToken(token, label, expires) {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
const body = {
|
||||
token: token,
|
||||
label: label,
|
||||
};
|
||||
if (expires > 0) {
|
||||
body.expires = Math.floor(Date.now() / 1000) + expires;
|
||||
}
|
||||
console.log(`[AccountApi] Creating user access token ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PATCH",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
}
|
||||
|
||||
async extendToken() {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
console.log(`[AccountApi] Extending user access token ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PATCH",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
});
|
||||
}
|
||||
|
||||
async deleteToken(token) {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
console.log(`[AccountApi] Deleting user access token ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({ "X-Token": token }, session.token()),
|
||||
});
|
||||
}
|
||||
|
||||
async updateSettings(payload) {
|
||||
const url = accountSettingsUrl(config.base_url);
|
||||
const body = JSON.stringify(payload);
|
||||
console.log(`[AccountApi] Updating user account ${url}: ${body}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PATCH",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: body,
|
||||
});
|
||||
}
|
||||
|
||||
async addSubscription(baseUrl, topic) {
|
||||
const url = accountSubscriptionUrl(config.base_url);
|
||||
const body = JSON.stringify({
|
||||
base_url: baseUrl,
|
||||
topic: topic,
|
||||
});
|
||||
console.log(`[AccountApi] Adding user subscription ${url}: ${body}`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: body,
|
||||
});
|
||||
const subscription = await response.json(); // May throw SyntaxError
|
||||
console.log(`[AccountApi] Subscription`, subscription);
|
||||
return subscription;
|
||||
}
|
||||
|
||||
async updateSubscription(baseUrl, topic, payload) {
|
||||
const url = accountSubscriptionUrl(config.base_url);
|
||||
const body = JSON.stringify({
|
||||
base_url: baseUrl,
|
||||
topic: topic,
|
||||
...payload,
|
||||
});
|
||||
console.log(`[AccountApi] Updating user subscription ${url}: ${body}`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: "PATCH",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: body,
|
||||
});
|
||||
const subscription = await response.json(); // May throw SyntaxError
|
||||
console.log(`[AccountApi] Subscription`, subscription);
|
||||
return subscription;
|
||||
}
|
||||
|
||||
async deleteSubscription(baseUrl, topic) {
|
||||
const url = accountSubscriptionUrl(config.base_url);
|
||||
console.log(`[AccountApi] Removing user subscription ${url}`);
|
||||
const headers = {
|
||||
"X-BaseURL": baseUrl,
|
||||
"X-Topic": topic,
|
||||
};
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth(headers, session.token()),
|
||||
});
|
||||
}
|
||||
|
||||
async upsertReservation(topic, everyone) {
|
||||
const url = accountReservationUrl(config.base_url);
|
||||
console.log(
|
||||
`[AccountApi] Upserting user access to topic ${topic}, everyone=${everyone}`
|
||||
);
|
||||
await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
topic: topic,
|
||||
everyone: everyone,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
async deleteReservation(topic, deleteMessages) {
|
||||
const url = accountReservationSingleUrl(config.base_url, topic);
|
||||
console.log(`[AccountApi] Removing topic reservation ${url}`);
|
||||
const headers = {
|
||||
"X-Delete-Messages": deleteMessages ? "true" : "false",
|
||||
};
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth(headers, session.token()),
|
||||
});
|
||||
}
|
||||
|
||||
async billingTiers() {
|
||||
if (this.tiers) {
|
||||
return this.tiers;
|
||||
}
|
||||
const url = tiersUrl(config.base_url);
|
||||
console.log(`[AccountApi] Fetching billing tiers`);
|
||||
const response = await fetchOrThrow(url); // No auth needed!
|
||||
this.tiers = await response.json(); // May throw SyntaxError
|
||||
return this.tiers;
|
||||
}
|
||||
|
||||
async createBillingSubscription(tier, interval) {
|
||||
console.log(
|
||||
`[AccountApi] Creating billing subscription with ${tier} and interval ${interval}`
|
||||
);
|
||||
return await this.upsertBillingSubscription("POST", tier, interval);
|
||||
}
|
||||
|
||||
async updateBillingSubscription(tier, interval) {
|
||||
console.log(
|
||||
`[AccountApi] Updating billing subscription with ${tier} and interval ${interval}`
|
||||
);
|
||||
return await this.upsertBillingSubscription("PUT", tier, interval);
|
||||
}
|
||||
|
||||
async upsertBillingSubscription(method, tier, interval) {
|
||||
const url = accountBillingSubscriptionUrl(config.base_url);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: method,
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
tier: tier,
|
||||
interval: interval,
|
||||
}),
|
||||
});
|
||||
return await response.json(); // May throw SyntaxError
|
||||
}
|
||||
|
||||
async deleteBillingSubscription() {
|
||||
const url = accountBillingSubscriptionUrl(config.base_url);
|
||||
console.log(`[AccountApi] Cancelling billing subscription`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
});
|
||||
}
|
||||
|
||||
async createBillingPortalSession() {
|
||||
const url = accountBillingPortalUrl(config.base_url);
|
||||
console.log(`[AccountApi] Creating billing portal session`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
});
|
||||
return await response.json(); // May throw SyntaxError
|
||||
}
|
||||
|
||||
async verifyPhoneNumber(phoneNumber, channel) {
|
||||
const url = accountPhoneVerifyUrl(config.base_url);
|
||||
console.log(`[AccountApi] Sending phone verification ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PUT",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
number: phoneNumber,
|
||||
channel: channel,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
async addPhoneNumber(phoneNumber, code) {
|
||||
const url = accountPhoneUrl(config.base_url);
|
||||
console.log(
|
||||
`[AccountApi] Adding phone number with verification code ${url}`
|
||||
);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PUT",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
number: phoneNumber,
|
||||
code: code,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
async deletePhoneNumber(phoneNumber, code) {
|
||||
const url = accountPhoneUrl(config.base_url);
|
||||
console.log(`[AccountApi] Deleting phone number ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
number: phoneNumber,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
async sync() {
|
||||
try {
|
||||
if (!session.token()) {
|
||||
return null;
|
||||
}
|
||||
console.log(`[AccountApi] Syncing account`);
|
||||
const account = await this.get();
|
||||
if (account.language) {
|
||||
await i18n.changeLanguage(account.language);
|
||||
}
|
||||
if (account.notification) {
|
||||
if (account.notification.sound) {
|
||||
await prefs.setSound(account.notification.sound);
|
||||
}
|
||||
return json.token;
|
||||
}
|
||||
|
||||
async logout() {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
console.log(`[AccountApi] Logging out from ${url} using token ${session.token()}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({}, session.token())
|
||||
});
|
||||
}
|
||||
|
||||
async create(username, password) {
|
||||
const url = accountUrl(config.base_url);
|
||||
const body = JSON.stringify({
|
||||
username: username,
|
||||
password: password
|
||||
});
|
||||
console.log(`[AccountApi] Creating user account ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
body: body
|
||||
});
|
||||
}
|
||||
|
||||
async get() {
|
||||
const url = accountUrl(config.base_url);
|
||||
console.log(`[AccountApi] Fetching user account ${url}`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
headers: maybeWithBearerAuth({}, session.token()) // GET /v1/account endpoint can be called by anonymous
|
||||
});
|
||||
const account = await response.json(); // May throw SyntaxError
|
||||
console.log(`[AccountApi] Account`, account);
|
||||
if (this.listener) {
|
||||
this.listener(account);
|
||||
if (account.notification.delete_after) {
|
||||
await prefs.setDeleteAfter(account.notification.delete_after);
|
||||
}
|
||||
return account;
|
||||
}
|
||||
|
||||
async delete(password) {
|
||||
const url = accountUrl(config.base_url);
|
||||
console.log(`[AccountApi] Deleting user account ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
password: password
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
async changePassword(currentPassword, newPassword) {
|
||||
const url = accountPasswordUrl(config.base_url);
|
||||
console.log(`[AccountApi] Changing account password ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
password: currentPassword,
|
||||
new_password: newPassword
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
async createToken(label, expires) {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
const body = {
|
||||
label: label,
|
||||
expires: (expires > 0) ? Math.floor(Date.now() / 1000) + expires : 0
|
||||
};
|
||||
console.log(`[AccountApi] Creating user access token ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
}
|
||||
|
||||
async updateToken(token, label, expires) {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
const body = {
|
||||
token: token,
|
||||
label: label
|
||||
};
|
||||
if (expires > 0) {
|
||||
body.expires = Math.floor(Date.now() / 1000) + expires;
|
||||
if (account.notification.min_priority) {
|
||||
await prefs.setMinPriority(account.notification.min_priority);
|
||||
}
|
||||
console.log(`[AccountApi] Creating user access token ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PATCH",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
}
|
||||
if (account.subscriptions) {
|
||||
await subscriptionManager.syncFromRemote(
|
||||
account.subscriptions,
|
||||
account.reservations
|
||||
);
|
||||
}
|
||||
return account;
|
||||
} catch (e) {
|
||||
console.log(`[AccountApi] Error fetching account`, e);
|
||||
if (e instanceof UnauthorizedError) {
|
||||
session.resetAndRedirect(routes.login);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async extendToken() {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
console.log(`[AccountApi] Extending user access token ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PATCH",
|
||||
headers: withBearerAuth({}, session.token())
|
||||
});
|
||||
startWorker() {
|
||||
if (this.timer !== null) {
|
||||
return;
|
||||
}
|
||||
console.log(`[AccountApi] Starting worker`);
|
||||
this.timer = setInterval(() => this.runWorker(), intervalMillis);
|
||||
setTimeout(() => this.runWorker(), delayMillis);
|
||||
}
|
||||
|
||||
async deleteToken(token) {
|
||||
const url = accountTokenUrl(config.base_url);
|
||||
console.log(`[AccountApi] Deleting user access token ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({"X-Token": token}, session.token())
|
||||
});
|
||||
async runWorker() {
|
||||
if (!session.token()) {
|
||||
return;
|
||||
}
|
||||
|
||||
async updateSettings(payload) {
|
||||
const url = accountSettingsUrl(config.base_url);
|
||||
const body = JSON.stringify(payload);
|
||||
console.log(`[AccountApi] Updating user account ${url}: ${body}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PATCH",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: body
|
||||
});
|
||||
}
|
||||
|
||||
async addSubscription(baseUrl, topic) {
|
||||
const url = accountSubscriptionUrl(config.base_url);
|
||||
const body = JSON.stringify({
|
||||
base_url: baseUrl,
|
||||
topic: topic
|
||||
});
|
||||
console.log(`[AccountApi] Adding user subscription ${url}: ${body}`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: body
|
||||
});
|
||||
const subscription = await response.json(); // May throw SyntaxError
|
||||
console.log(`[AccountApi] Subscription`, subscription);
|
||||
return subscription;
|
||||
}
|
||||
|
||||
async updateSubscription(baseUrl, topic, payload) {
|
||||
const url = accountSubscriptionUrl(config.base_url);
|
||||
const body = JSON.stringify({
|
||||
base_url: baseUrl,
|
||||
topic: topic,
|
||||
...payload
|
||||
});
|
||||
console.log(`[AccountApi] Updating user subscription ${url}: ${body}`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: "PATCH",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: body
|
||||
});
|
||||
const subscription = await response.json(); // May throw SyntaxError
|
||||
console.log(`[AccountApi] Subscription`, subscription);
|
||||
return subscription;
|
||||
}
|
||||
|
||||
async deleteSubscription(baseUrl, topic) {
|
||||
const url = accountSubscriptionUrl(config.base_url);
|
||||
console.log(`[AccountApi] Removing user subscription ${url}`);
|
||||
const headers = {
|
||||
"X-BaseURL": baseUrl,
|
||||
"X-Topic": topic,
|
||||
}
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth(headers, session.token()),
|
||||
});
|
||||
}
|
||||
|
||||
async upsertReservation(topic, everyone) {
|
||||
const url = accountReservationUrl(config.base_url);
|
||||
console.log(`[AccountApi] Upserting user access to topic ${topic}, everyone=${everyone}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
topic: topic,
|
||||
everyone: everyone
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
async deleteReservation(topic, deleteMessages) {
|
||||
const url = accountReservationSingleUrl(config.base_url, topic);
|
||||
console.log(`[AccountApi] Removing topic reservation ${url}`);
|
||||
const headers = {
|
||||
"X-Delete-Messages": deleteMessages ? "true" : "false"
|
||||
}
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth(headers, session.token())
|
||||
});
|
||||
}
|
||||
|
||||
async billingTiers() {
|
||||
if (this.tiers) {
|
||||
return this.tiers;
|
||||
}
|
||||
const url = tiersUrl(config.base_url);
|
||||
console.log(`[AccountApi] Fetching billing tiers`);
|
||||
const response = await fetchOrThrow(url); // No auth needed!
|
||||
this.tiers = await response.json(); // May throw SyntaxError
|
||||
return this.tiers;
|
||||
}
|
||||
|
||||
async createBillingSubscription(tier, interval) {
|
||||
console.log(`[AccountApi] Creating billing subscription with ${tier} and interval ${interval}`);
|
||||
return await this.upsertBillingSubscription("POST", tier, interval)
|
||||
}
|
||||
|
||||
async updateBillingSubscription(tier, interval) {
|
||||
console.log(`[AccountApi] Updating billing subscription with ${tier} and interval ${interval}`);
|
||||
return await this.upsertBillingSubscription("PUT", tier, interval)
|
||||
}
|
||||
|
||||
async upsertBillingSubscription(method, tier, interval) {
|
||||
const url = accountBillingSubscriptionUrl(config.base_url);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: method,
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
tier: tier,
|
||||
interval: interval
|
||||
})
|
||||
});
|
||||
return await response.json(); // May throw SyntaxError
|
||||
}
|
||||
|
||||
async deleteBillingSubscription() {
|
||||
const url = accountBillingSubscriptionUrl(config.base_url);
|
||||
console.log(`[AccountApi] Cancelling billing subscription`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({}, session.token())
|
||||
});
|
||||
}
|
||||
|
||||
async createBillingPortalSession() {
|
||||
const url = accountBillingPortalUrl(config.base_url);
|
||||
console.log(`[AccountApi] Creating billing portal session`);
|
||||
const response = await fetchOrThrow(url, {
|
||||
method: "POST",
|
||||
headers: withBearerAuth({}, session.token())
|
||||
});
|
||||
return await response.json(); // May throw SyntaxError
|
||||
}
|
||||
|
||||
async verifyPhoneNumber(phoneNumber, channel) {
|
||||
const url = accountPhoneVerifyUrl(config.base_url);
|
||||
console.log(`[AccountApi] Sending phone verification ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PUT",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
number: phoneNumber,
|
||||
channel: channel
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
async addPhoneNumber(phoneNumber, code) {
|
||||
const url = accountPhoneUrl(config.base_url);
|
||||
console.log(`[AccountApi] Adding phone number with verification code ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "PUT",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
number: phoneNumber,
|
||||
code: code
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
async deletePhoneNumber(phoneNumber, code) {
|
||||
const url = accountPhoneUrl(config.base_url);
|
||||
console.log(`[AccountApi] Deleting phone number ${url}`);
|
||||
await fetchOrThrow(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({}, session.token()),
|
||||
body: JSON.stringify({
|
||||
number: phoneNumber
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
async sync() {
|
||||
try {
|
||||
if (!session.token()) {
|
||||
return null;
|
||||
}
|
||||
console.log(`[AccountApi] Syncing account`);
|
||||
const account = await this.get();
|
||||
if (account.language) {
|
||||
await i18n.changeLanguage(account.language);
|
||||
}
|
||||
if (account.notification) {
|
||||
if (account.notification.sound) {
|
||||
await prefs.setSound(account.notification.sound);
|
||||
}
|
||||
if (account.notification.delete_after) {
|
||||
await prefs.setDeleteAfter(account.notification.delete_after);
|
||||
}
|
||||
if (account.notification.min_priority) {
|
||||
await prefs.setMinPriority(account.notification.min_priority);
|
||||
}
|
||||
}
|
||||
if (account.subscriptions) {
|
||||
await subscriptionManager.syncFromRemote(account.subscriptions, account.reservations);
|
||||
}
|
||||
return account;
|
||||
} catch (e) {
|
||||
console.log(`[AccountApi] Error fetching account`, e);
|
||||
if (e instanceof UnauthorizedError) {
|
||||
session.resetAndRedirect(routes.login);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startWorker() {
|
||||
if (this.timer !== null) {
|
||||
return;
|
||||
}
|
||||
console.log(`[AccountApi] Starting worker`);
|
||||
this.timer = setInterval(() => this.runWorker(), intervalMillis);
|
||||
setTimeout(() => this.runWorker(), delayMillis);
|
||||
}
|
||||
|
||||
async runWorker() {
|
||||
if (!session.token()) {
|
||||
return;
|
||||
}
|
||||
console.log(`[AccountApi] Extending user access token`);
|
||||
try {
|
||||
await this.extendToken();
|
||||
} catch (e) {
|
||||
console.log(`[AccountApi] Error extending user access token`, e);
|
||||
}
|
||||
console.log(`[AccountApi] Extending user access token`);
|
||||
try {
|
||||
await this.extendToken();
|
||||
} catch (e) {
|
||||
console.log(`[AccountApi] Error extending user access token`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maps to user.Role in user/types.go
|
||||
export const Role = {
|
||||
ADMIN: "admin",
|
||||
USER: "user"
|
||||
ADMIN: "admin",
|
||||
USER: "user",
|
||||
};
|
||||
|
||||
// Maps to server.visitorLimitBasis in server/visitor.go
|
||||
export const LimitBasis = {
|
||||
IP: "ip",
|
||||
TIER: "tier"
|
||||
IP: "ip",
|
||||
TIER: "tier",
|
||||
};
|
||||
|
||||
// Maps to stripe.SubscriptionStatus
|
||||
export const SubscriptionStatus = {
|
||||
ACTIVE: "active",
|
||||
PAST_DUE: "past_due"
|
||||
ACTIVE: "active",
|
||||
PAST_DUE: "past_due",
|
||||
};
|
||||
|
||||
// Maps to stripe.PriceRecurringInterval
|
||||
export const SubscriptionInterval = {
|
||||
MONTH: "month",
|
||||
YEAR: "year"
|
||||
MONTH: "month",
|
||||
YEAR: "year",
|
||||
};
|
||||
|
||||
// Maps to user.Permission in user/types.go
|
||||
export const Permission = {
|
||||
READ_WRITE: "read-write",
|
||||
READ_ONLY: "read-only",
|
||||
WRITE_ONLY: "write-only",
|
||||
DENY_ALL: "deny-all"
|
||||
READ_WRITE: "read-write",
|
||||
READ_ONLY: "read-only",
|
||||
WRITE_ONLY: "write-only",
|
||||
DENY_ALL: "deny-all",
|
||||
};
|
||||
|
||||
const accountApi = new AccountApi();
|
||||
|
||||
Reference in New Issue
Block a user