summaryrefslogtreecommitdiff
path: root/web/source/settings/lib/query
diff options
context:
space:
mode:
Diffstat (limited to 'web/source/settings/lib/query')
-rw-r--r--web/source/settings/lib/query/admin/custom-emoji.js2
-rw-r--r--web/source/settings/lib/query/admin/import-export.js2
-rw-r--r--web/source/settings/lib/query/admin/index.js6
-rw-r--r--web/source/settings/lib/query/admin/reports.js2
-rw-r--r--web/source/settings/lib/query/base.js70
-rw-r--r--web/source/settings/lib/query/gts-api.ts149
-rw-r--r--web/source/settings/lib/query/index.js6
-rw-r--r--web/source/settings/lib/query/lib.js6
-rw-r--r--web/source/settings/lib/query/oauth.js160
-rw-r--r--web/source/settings/lib/query/oauth/index.ts204
-rw-r--r--web/source/settings/lib/query/user/index.ts (renamed from web/source/settings/lib/query/user.js)43
11 files changed, 382 insertions, 268 deletions
diff --git a/web/source/settings/lib/query/admin/custom-emoji.js b/web/source/settings/lib/query/admin/custom-emoji.js
index c84155efd..6e7c772a2 100644
--- a/web/source/settings/lib/query/admin/custom-emoji.js
+++ b/web/source/settings/lib/query/admin/custom-emoji.js
@@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-"use strict";
-
const Promise = require("bluebird");
const { unwrapRes } = require("../lib");
diff --git a/web/source/settings/lib/query/admin/import-export.js b/web/source/settings/lib/query/admin/import-export.js
index 7c44d8280..9a04438c2 100644
--- a/web/source/settings/lib/query/admin/import-export.js
+++ b/web/source/settings/lib/query/admin/import-export.js
@@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-"use strict";
-
const Promise = require("bluebird");
const fileDownload = require("js-file-download");
const csv = require("papaparse");
diff --git a/web/source/settings/lib/query/admin/index.js b/web/source/settings/lib/query/admin/index.js
index 7b46e6ba4..7a55389d3 100644
--- a/web/source/settings/lib/query/admin/index.js
+++ b/web/source/settings/lib/query/admin/index.js
@@ -17,15 +17,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-"use strict";
-
const {
replaceCacheOnMutation,
removeFromCacheOnMutation,
domainListToObject,
idListToObject
} = require("../lib");
-const base = require("../base");
+const { gtsApi } = require("../gts-api");
const endpoints = (build) => ({
updateInstance: build.mutation({
@@ -164,4 +162,4 @@ const endpoints = (build) => ({
...require("./reports")(build)
});
-module.exports = base.injectEndpoints({ endpoints }); \ No newline at end of file
+module.exports = gtsApi.injectEndpoints({ endpoints }); \ No newline at end of file
diff --git a/web/source/settings/lib/query/admin/reports.js b/web/source/settings/lib/query/admin/reports.js
index 28940872c..1c45bb7bc 100644
--- a/web/source/settings/lib/query/admin/reports.js
+++ b/web/source/settings/lib/query/admin/reports.js
@@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-"use strict";
-
module.exports = (build) => ({
listReports: build.query({
query: (params = {}) => ({
diff --git a/web/source/settings/lib/query/base.js b/web/source/settings/lib/query/base.js
deleted file mode 100644
index ba02d4e07..000000000
--- a/web/source/settings/lib/query/base.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- GoToSocial
- Copyright (C) GoToSocial Authors admin@gotosocial.org
- SPDX-License-Identifier: AGPL-3.0-or-later
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const { createApi, fetchBaseQuery } = require("@reduxjs/toolkit/query/react");
-const { serialize: serializeForm } = require("object-to-formdata");
-
-function instanceBasedQuery(args, api, extraOptions) {
- const state = api.getState();
- const { instance, token } = state.oauth;
-
- if (args.baseUrl == undefined) {
- args.baseUrl = instance;
- }
-
- if (args.discardEmpty) {
- if (args.body == undefined || Object.keys(args.body).length == 0) {
- return { data: null };
- }
- delete args.discardEmpty;
- }
-
- if (args.asForm) {
- delete args.asForm;
- args.body = serializeForm(args.body, {
- indices: true, // Array indices, for profile fields
- });
- }
-
- return fetchBaseQuery({
- baseUrl: args.baseUrl,
- prepareHeaders: (headers) => {
- if (token != undefined) {
- headers.set('Authorization', token);
- }
- headers.set("Accept", "application/json");
- return headers;
- },
- })(args, api, extraOptions);
-}
-
-module.exports = createApi({
- reducerPath: "api",
- baseQuery: instanceBasedQuery,
- tagTypes: ["Auth", "Emoji", "Reports", "Account", "InstanceRules"],
- endpoints: (build) => ({
- instance: build.query({
- query: () => ({
- url: `/api/v1/instance`
- })
- })
- })
-}); \ No newline at end of file
diff --git a/web/source/settings/lib/query/gts-api.ts b/web/source/settings/lib/query/gts-api.ts
new file mode 100644
index 000000000..9e043137c
--- /dev/null
+++ b/web/source/settings/lib/query/gts-api.ts
@@ -0,0 +1,149 @@
+/*
+ GoToSocial
+ Copyright (C) GoToSocial Authors admin@gotosocial.org
+ SPDX-License-Identifier: AGPL-3.0-or-later
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
+import type {
+ BaseQueryFn,
+ FetchArgs,
+ FetchBaseQueryError,
+} from '@reduxjs/toolkit/query/react';
+import { serialize as serializeForm } from "object-to-formdata";
+
+import type { RootState } from '../../redux/store';
+
+/**
+ * GTSFetchArgs extends standard FetchArgs used by
+ * RTK Query with a couple helpers of our own.
+ */
+export interface GTSFetchArgs extends FetchArgs {
+ /**
+ * If provided, will be used as base URL. Else,
+ * will fall back to authorized instance as baseUrl.
+ */
+ baseUrl?: string;
+ /**
+ * If true, and no args.body is set, or args.body is empty,
+ * then a null response will be returned from the API call.
+ */
+ discardEmpty?: boolean;
+ /**
+ * If true, then args.body will be serialized
+ * as FormData before submission.
+ */
+ asForm?: boolean;
+}
+
+/**
+ * gtsBaseQuery wraps the redux toolkit fetchBaseQuery with some helper functionality.
+ *
+ * For an explainer of what's happening in this function, see:
+ * - https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#customizing-queries-with-basequery
+ * - https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#constructing-a-dynamic-base-url-using-redux-state
+ *
+ * @param args
+ * @param api
+ * @param extraOptions
+ * @returns
+ */
+const gtsBaseQuery: BaseQueryFn<
+ string | GTSFetchArgs,
+ any,
+ FetchBaseQueryError
+> = async (args, api, extraOptions) => {
+ // Retrieve state at the moment
+ // this function was called.
+ const state = api.getState() as RootState;
+ const { instanceUrl, token } = state.oauth;
+
+ // Derive baseUrl dynamically.
+ let baseUrl: string;
+
+ // Check if simple string baseUrl provided
+ // as args, or if more complex args provided.
+ if (typeof args === "string") {
+ baseUrl = args;
+ } else {
+ if (args.baseUrl != undefined) {
+ baseUrl = args.baseUrl;
+ } else {
+ baseUrl = instanceUrl;
+ }
+
+ if (args.discardEmpty) {
+ if (args.body == undefined || Object.keys(args.body).length == 0) {
+ return { data: null };
+ }
+ }
+
+ if (args.asForm) {
+ args.body = serializeForm(args.body, {
+ // Array indices, for profile fields.
+ indices: true,
+ });
+ }
+
+ // Delete any of our extended arguments
+ // to avoid confusing fetchBaseQuery.
+ delete args.baseUrl;
+ delete args.discardEmpty;
+ delete args.asForm;
+ }
+
+ if (!baseUrl) {
+ return {
+ error: {
+ status: 400,
+ statusText: 'Bad Request',
+ data: {"error":"No baseUrl set for request"},
+ },
+ };
+ }
+
+ return fetchBaseQuery({
+ baseUrl: baseUrl,
+ prepareHeaders: (headers) => {
+ if (token != undefined) {
+ headers.set('Authorization', token);
+ }
+ headers.set("Accept", "application/json");
+ return headers;
+ },
+ })(args, api, extraOptions);
+};
+
+export const gtsApi = createApi({
+ reducerPath: "api",
+ baseQuery: gtsBaseQuery,
+ tagTypes: [
+ "Auth",
+ "Emoji",
+ "Reports",
+ "Account",
+ "InstanceRules",
+ ],
+ endpoints: (builder) => ({
+ instance: builder.query<any, void>({
+ query: () => ({
+ url: `/api/v1/instance`
+ })
+ })
+ })
+});
+
+export const { useInstanceQuery } = gtsApi;
diff --git a/web/source/settings/lib/query/index.js b/web/source/settings/lib/query/index.js
index dab896f80..aeaa4a1d7 100644
--- a/web/source/settings/lib/query/index.js
+++ b/web/source/settings/lib/query/index.js
@@ -17,11 +17,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-"use strict";
-
module.exports = {
- ...require("./base"),
+ ...require("./gts-api"),
...require("./oauth"),
...require("./user"),
...require("./admin")
-}; \ No newline at end of file
+};
diff --git a/web/source/settings/lib/query/lib.js b/web/source/settings/lib/query/lib.js
index 56ce05478..1025ca3a7 100644
--- a/web/source/settings/lib/query/lib.js
+++ b/web/source/settings/lib/query/lib.js
@@ -17,10 +17,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-"use strict";
-
const syncpipe = require("syncpipe");
-const base = require("./base");
+const { gtsApi } = require("./gts-api");
module.exports = {
unwrapRes(res) {
@@ -70,7 +68,7 @@ function makeCacheMutation(action) {
return {
onQueryStarted: (_, { dispatch, queryFulfilled }) => {
queryFulfilled.then(({ data: newData }) => {
- dispatch(base.util.updateQueryData(queryName, arg, (draft) => {
+ dispatch(gtsApi.util.updateQueryData(queryName, arg, (draft) => {
if (findKey != undefined) {
key = findKey(draft, newData);
}
diff --git a/web/source/settings/lib/query/oauth.js b/web/source/settings/lib/query/oauth.js
deleted file mode 100644
index 7284ee856..000000000
--- a/web/source/settings/lib/query/oauth.js
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- GoToSocial
- Copyright (C) GoToSocial Authors admin@gotosocial.org
- SPDX-License-Identifier: AGPL-3.0-or-later
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const Promise = require("bluebird");
-
-const base = require("./base");
-const { unwrapRes } = require("./lib");
-const oauth = require("../../redux/oauth").actions;
-
-function getSettingsURL() {
- /* needed in case the settings interface isn't hosted at /settings but
- some subpath like /gotosocial/settings. Other parts of the code don't
- take this into account yet so mostly future-proofing.
-
- Also drops anything past /settings/, because authorization urls that are too long
- get rejected by GTS.
- */
- let [pre, _past] = window.location.pathname.split("/settings");
- return `${window.location.origin}${pre}/settings`;
-}
-
-const SETTINGS_URL = getSettingsURL();
-
-const endpoints = (build) => ({
- verifyCredentials: build.query({
- providesTags: (_res, error) =>
- error == undefined
- ? ["Auth"]
- : [],
- queryFn: (_arg, api, _extraOpts, baseQuery) => {
- const state = api.getState();
-
- return Promise.try(() => {
- // Process callback code first, if available
- if (state.oauth.loginState == "callback") {
- let urlParams = new URLSearchParams(window.location.search);
- let code = urlParams.get("code");
-
- if (code == undefined) {
- throw {
- message: "Waiting for callback, but no ?code= provided in url."
- };
- } else {
- let app = state.oauth.registration;
-
- if (app == undefined || app.client_id == undefined) {
- throw {
- message: "No stored registration data, can't finish login flow."
- };
- }
-
- return baseQuery({
- method: "POST",
- url: "/oauth/token",
- body: {
- client_id: app.client_id,
- client_secret: app.client_secret,
- redirect_uri: SETTINGS_URL,
- grant_type: "authorization_code",
- code: code
- }
- }).then(unwrapRes).then((token) => {
- // remove ?code= from url
- window.history.replaceState({}, document.title, window.location.pathname);
- api.dispatch(oauth.setToken(token));
- });
- }
- }
- }).then(() => {
- return baseQuery({
- url: `/api/v1/accounts/verify_credentials`
- });
- }).catch((e) => {
- return { error: e };
- });
- }
- }),
- authorizeFlow: build.mutation({
- queryFn: (formData, api, _extraOpts, baseQuery) => {
- let instance;
- const state = api.getState();
-
- return Promise.try(() => {
- if (!formData.instance.startsWith("http")) {
- formData.instance = `https://${formData.instance}`;
- }
- instance = new URL(formData.instance).origin;
-
- const stored = state.oauth.instance;
- if (stored?.instance == instance && stored.registration) {
- return stored.registration;
- }
-
- return baseQuery({
- method: "POST",
- baseUrl: instance,
- url: "/api/v1/apps",
- body: {
- client_name: "GoToSocial Settings",
- scopes: formData.scopes,
- redirect_uris: SETTINGS_URL,
- website: SETTINGS_URL
- }
- }).then(unwrapRes).then((app) => {
- app.scopes = formData.scopes;
-
- api.dispatch(oauth.authorize({
- instance: instance,
- registration: app,
- loginState: "callback",
- expectingRedirect: true
- }));
-
- return app;
- });
- }).then((app) => {
- let url = new URL(instance);
- url.pathname = "/oauth/authorize";
- url.searchParams.set("client_id", app.client_id);
- url.searchParams.set("redirect_uri", SETTINGS_URL);
- url.searchParams.set("response_type", "code");
- url.searchParams.set("scope", app.scopes);
-
- let redirectURL = url.toString();
- window.location.assign(redirectURL);
-
- return { data: null };
- }).catch((e) => {
- return { error: e };
- });
- },
- }),
- logout: build.mutation({
- queryFn: (_arg, api) => {
- api.dispatch(oauth.remove());
- return { data: null };
- },
- invalidatesTags: ["Auth"]
- })
-});
-
-module.exports = base.injectEndpoints({ endpoints }); \ No newline at end of file
diff --git a/web/source/settings/lib/query/oauth/index.ts b/web/source/settings/lib/query/oauth/index.ts
new file mode 100644
index 000000000..9af2dd5fb
--- /dev/null
+++ b/web/source/settings/lib/query/oauth/index.ts
@@ -0,0 +1,204 @@
+/*
+ GoToSocial
+ Copyright (C) GoToSocial Authors admin@gotosocial.org
+ SPDX-License-Identifier: AGPL-3.0-or-later
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+import type { FetchBaseQueryError } from '@reduxjs/toolkit/query';
+
+import { gtsApi } from "../gts-api";
+import {
+ setToken as oauthSetToken,
+ remove as oauthRemove,
+ authorize as oauthAuthorize,
+} from "../../../redux/oauth";
+import { RootState } from '../../../redux/store';
+
+export interface OauthTokenRequestBody {
+ client_id: string;
+ client_secret: string;
+ redirect_uri: string;
+ grant_type: string;
+ code: string;
+}
+
+function getSettingsURL() {
+ /*
+ needed in case the settings interface isn't hosted at /settings but
+ some subpath like /gotosocial/settings. Other parts of the code don't
+ take this into account yet so mostly future-proofing.
+
+ Also drops anything past /settings/, because authorization urls that are too long
+ get rejected by GTS.
+ */
+ let [pre, _past] = window.location.pathname.split("/settings");
+ return `${window.location.origin}${pre}/settings`;
+}
+
+const SETTINGS_URL = (getSettingsURL());
+
+// Couple auth functions here require multiple requests as
+// part of an OAuth token 'flow'. To keep things simple for
+// callers of these query functions, the multiple requests
+// are chained within one query.
+//
+// https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#performing-multiple-requests-with-a-single-query
+const extended = gtsApi.injectEndpoints({
+ endpoints: (builder) => ({
+ verifyCredentials: builder.query<any, void>({
+ providesTags: (_res, error) =>
+ error == undefined ? ["Auth"] : [],
+ async queryFn(_arg, api, _extraOpts, fetchWithBQ) {
+ const state = api.getState() as RootState;
+ const oauthState = state.oauth;
+
+ // If we're not in the middle of an auth/callback,
+ // we may already have an auth token, so just
+ // return a standard verify_credentials query.
+ if (oauthState.loginState != 'callback') {
+ return fetchWithBQ({
+ url: `/api/v1/accounts/verify_credentials`
+ });
+ }
+
+ // We're in the middle of an auth/callback flow.
+ // Try to retrieve callback code from URL query.
+ let urlParams = new URLSearchParams(window.location.search);
+ let code = urlParams.get("code");
+ if (code == undefined) {
+ return {
+ error: {
+ status: 400,
+ statusText: 'Bad Request',
+ data: {"error":"Waiting for callback, but no ?code= provided in url."},
+ },
+ };
+ }
+
+ // Retrieve app with which the
+ // callback code was generated.
+ let app = oauthState.app;
+ if (app == undefined || app.client_id == undefined) {
+ return {
+ error: {
+ status: 400,
+ statusText: 'Bad Request',
+ data: {"error":"No stored app registration data, can't finish login flow."},
+ },
+ };
+ }
+
+ // Use the provided code and app
+ // secret to request an auth token.
+ const tokenReqBody: OauthTokenRequestBody = {
+ client_id: app.client_id,
+ client_secret: app.client_secret,
+ redirect_uri: SETTINGS_URL,
+ grant_type: "authorization_code",
+ code: code
+ };
+
+ const tokenResult = await fetchWithBQ({
+ method: "POST",
+ url: "/oauth/token",
+ body: tokenReqBody,
+ });
+ if (tokenResult.error) {
+ return { error: tokenResult.error as FetchBaseQueryError };
+ }
+
+ // Remove ?code= query param from
+ // url, we don't want it anymore.
+ window.history.replaceState({}, document.title, window.location.pathname);
+
+ // Store returned token in redux.
+ api.dispatch(oauthSetToken(tokenResult.data));
+
+ // We're now authed! So return
+ // standard verify_credentials query.
+ return fetchWithBQ({
+ url: `/api/v1/accounts/verify_credentials`
+ });
+ }
+ }),
+
+ authorizeFlow: builder.mutation({
+ async queryFn(formData, api, _extraOpts, fetchWithBQ) {
+ const state = api.getState() as RootState;
+ const oauthState = state.oauth;
+
+ let instanceUrl: string;
+ if (!formData.instance.startsWith("http")) {
+ formData.instance = `https://${formData.instance}`;
+ }
+
+ instanceUrl = new URL(formData.instance).origin;
+ if (oauthState?.instanceUrl == instanceUrl && oauthState.app) {
+ return { data: oauthState.app };
+ }
+
+ const appResult = await fetchWithBQ({
+ method: "POST",
+ baseUrl: instanceUrl,
+ url: "/api/v1/apps",
+ body: {
+ client_name: "GoToSocial Settings",
+ scopes: formData.scopes,
+ redirect_uris: SETTINGS_URL,
+ website: SETTINGS_URL
+ }
+ });
+ if (appResult.error) {
+ return { error: appResult.error as FetchBaseQueryError };
+ }
+
+ let app = appResult.data as any;
+
+ app.scopes = formData.scopes;
+ api.dispatch(oauthAuthorize({
+ instanceUrl: instanceUrl,
+ app: app,
+ loginState: "callback",
+ expectingRedirect: true
+ }));
+
+ let url = new URL(instanceUrl);
+ url.pathname = "/oauth/authorize";
+ url.searchParams.set("client_id", app.client_id);
+ url.searchParams.set("redirect_uri", SETTINGS_URL);
+ url.searchParams.set("response_type", "code");
+ url.searchParams.set("scope", app.scopes);
+
+ let redirectURL = url.toString();
+ window.location.assign(redirectURL);
+ return { data: null };
+ },
+ }),
+ logout: builder.mutation({
+ queryFn: (_arg, api) => {
+ api.dispatch(oauthRemove());
+ return { data: null };
+ },
+ invalidatesTags: ["Auth"]
+ })
+ })
+});
+
+export const {
+ useVerifyCredentialsQuery,
+ useAuthorizeFlowMutation,
+ useLogoutMutation,
+} = extended; \ No newline at end of file
diff --git a/web/source/settings/lib/query/user.js b/web/source/settings/lib/query/user/index.ts
index a88e16035..751e38e5b 100644
--- a/web/source/settings/lib/query/user.js
+++ b/web/source/settings/lib/query/user/index.ts
@@ -17,29 +17,32 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-"use strict";
+import { replaceCacheOnMutation } from "../lib";
+import { gtsApi } from "../gts-api";
-const { replaceCacheOnMutation } = require("./lib");
-const base = require("./base");
-
-const endpoints = (build) => ({
- updateCredentials: build.mutation({
- query: (formData) => ({
- method: "PATCH",
- url: `/api/v1/accounts/update_credentials`,
- asForm: true,
- body: formData,
- discardEmpty: true
+const extended = gtsApi.injectEndpoints({
+ endpoints: (builder) => ({
+ updateCredentials: builder.mutation({
+ query: (formData) => ({
+ method: "PATCH",
+ url: `/api/v1/accounts/update_credentials`,
+ asForm: true,
+ body: formData,
+ discardEmpty: true
+ }),
+ ...replaceCacheOnMutation("verifyCredentials")
}),
- ...replaceCacheOnMutation("verifyCredentials")
- }),
- passwordChange: build.mutation({
- query: (data) => ({
- method: "POST",
- url: `/api/v1/user/password_change`,
- body: data
+ passwordChange: builder.mutation({
+ query: (data) => ({
+ method: "POST",
+ url: `/api/v1/user/password_change`,
+ body: data
+ })
})
})
});
-module.exports = base.injectEndpoints({ endpoints }); \ No newline at end of file
+export const {
+ useUpdateCredentialsMutation,
+ usePasswordChangeMutation,
+} = extended;