466 lines
18 KiB
JavaScript
466 lines
18 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const tslib_1 = require("tslib");
|
|
const fetch_1 = require("./lib/fetch");
|
|
const helpers_1 = require("./lib/helpers");
|
|
const types_1 = require("./lib/types");
|
|
const errors_1 = require("./lib/errors");
|
|
class GoTrueAdminApi {
|
|
/**
|
|
* Creates an admin API client that can be used to manage users and OAuth clients.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* import { GoTrueAdminApi } from '@supabase/auth-js'
|
|
*
|
|
* const admin = new GoTrueAdminApi({
|
|
* url: 'https://xyzcompany.supabase.co/auth/v1',
|
|
* headers: { Authorization: `Bearer ${process.env.SUPABASE_SERVICE_ROLE_KEY}` },
|
|
* })
|
|
* ```
|
|
*/
|
|
constructor({ url = '', headers = {}, fetch, }) {
|
|
this.url = url;
|
|
this.headers = headers;
|
|
this.fetch = (0, helpers_1.resolveFetch)(fetch);
|
|
this.mfa = {
|
|
listFactors: this._listFactors.bind(this),
|
|
deleteFactor: this._deleteFactor.bind(this),
|
|
};
|
|
this.oauth = {
|
|
listClients: this._listOAuthClients.bind(this),
|
|
createClient: this._createOAuthClient.bind(this),
|
|
getClient: this._getOAuthClient.bind(this),
|
|
updateClient: this._updateOAuthClient.bind(this),
|
|
deleteClient: this._deleteOAuthClient.bind(this),
|
|
regenerateClientSecret: this._regenerateOAuthClientSecret.bind(this),
|
|
};
|
|
}
|
|
/**
|
|
* Removes a logged-in session.
|
|
* @param jwt A valid, logged-in JWT.
|
|
* @param scope The logout sope.
|
|
*/
|
|
async signOut(jwt, scope = types_1.SIGN_OUT_SCOPES[0]) {
|
|
if (types_1.SIGN_OUT_SCOPES.indexOf(scope) < 0) {
|
|
throw new Error(`@supabase/auth-js: Parameter scope must be one of ${types_1.SIGN_OUT_SCOPES.join(', ')}`);
|
|
}
|
|
try {
|
|
await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/logout?scope=${scope}`, {
|
|
headers: this.headers,
|
|
jwt,
|
|
noResolveJson: true,
|
|
});
|
|
return { data: null, error: null };
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: null, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Sends an invite link to an email address.
|
|
* @param email The email address of the user.
|
|
* @param options Additional options to be included when inviting.
|
|
*/
|
|
async inviteUserByEmail(email, options = {}) {
|
|
try {
|
|
return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/invite`, {
|
|
body: { email, data: options.data },
|
|
headers: this.headers,
|
|
redirectTo: options.redirectTo,
|
|
xform: fetch_1._userResponse,
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: { user: null }, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Generates email links and OTPs to be sent via a custom email provider.
|
|
* @param email The user's email.
|
|
* @param options.password User password. For signup only.
|
|
* @param options.data Optional user metadata. For signup only.
|
|
* @param options.redirectTo The redirect url which should be appended to the generated link
|
|
*/
|
|
async generateLink(params) {
|
|
try {
|
|
const { options } = params, rest = tslib_1.__rest(params, ["options"]);
|
|
const body = Object.assign(Object.assign({}, rest), options);
|
|
if ('newEmail' in rest) {
|
|
// replace newEmail with new_email in request body
|
|
body.new_email = rest === null || rest === void 0 ? void 0 : rest.newEmail;
|
|
delete body['newEmail'];
|
|
}
|
|
return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/admin/generate_link`, {
|
|
body: body,
|
|
headers: this.headers,
|
|
xform: fetch_1._generateLinkResponse,
|
|
redirectTo: options === null || options === void 0 ? void 0 : options.redirectTo,
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return {
|
|
data: {
|
|
properties: null,
|
|
user: null,
|
|
},
|
|
error,
|
|
};
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
// User Admin API
|
|
/**
|
|
* Creates a new user.
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*/
|
|
async createUser(attributes) {
|
|
try {
|
|
return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/admin/users`, {
|
|
body: attributes,
|
|
headers: this.headers,
|
|
xform: fetch_1._userResponse,
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: { user: null }, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Get a list of users.
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
* @param params An object which supports `page` and `perPage` as numbers, to alter the paginated results.
|
|
*/
|
|
async listUsers(params) {
|
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
try {
|
|
const pagination = { nextPage: null, lastPage: 0, total: 0 };
|
|
const response = await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/admin/users`, {
|
|
headers: this.headers,
|
|
noResolveJson: true,
|
|
query: {
|
|
page: (_b = (_a = params === null || params === void 0 ? void 0 : params.page) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '',
|
|
per_page: (_d = (_c = params === null || params === void 0 ? void 0 : params.perPage) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '',
|
|
},
|
|
xform: fetch_1._noResolveJsonResponse,
|
|
});
|
|
if (response.error)
|
|
throw response.error;
|
|
const users = await response.json();
|
|
const total = (_e = response.headers.get('x-total-count')) !== null && _e !== void 0 ? _e : 0;
|
|
const links = (_g = (_f = response.headers.get('link')) === null || _f === void 0 ? void 0 : _f.split(',')) !== null && _g !== void 0 ? _g : [];
|
|
if (links.length > 0) {
|
|
links.forEach((link) => {
|
|
const page = parseInt(link.split(';')[0].split('=')[1].substring(0, 1));
|
|
const rel = JSON.parse(link.split(';')[1].split('=')[1]);
|
|
pagination[`${rel}Page`] = page;
|
|
});
|
|
pagination.total = parseInt(total);
|
|
}
|
|
return { data: Object.assign(Object.assign({}, users), pagination), error: null };
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: { users: [] }, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Get user by id.
|
|
*
|
|
* @param uid The user's unique identifier
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*/
|
|
async getUserById(uid) {
|
|
(0, helpers_1.validateUUID)(uid);
|
|
try {
|
|
return await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/admin/users/${uid}`, {
|
|
headers: this.headers,
|
|
xform: fetch_1._userResponse,
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: { user: null }, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Updates the user data. Changes are applied directly without confirmation flows.
|
|
*
|
|
* @param uid The user's unique identifier
|
|
* @param attributes The data you want to update.
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*
|
|
* @remarks
|
|
* **Important:** This is a server-side operation and does **not** trigger client-side
|
|
* `onAuthStateChange` listeners. The admin API has no connection to client state.
|
|
*
|
|
* To sync changes to the client after calling this method:
|
|
* 1. On the client, call `supabase.auth.refreshSession()` to fetch the updated user data
|
|
* 2. This will trigger the `TOKEN_REFRESHED` event and notify all listeners
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* // Server-side (Edge Function)
|
|
* const { data, error } = await supabase.auth.admin.updateUserById(
|
|
* userId,
|
|
* { user_metadata: { preferences: { theme: 'dark' } } }
|
|
* )
|
|
*
|
|
* // Client-side (to sync the changes)
|
|
* const { data, error } = await supabase.auth.refreshSession()
|
|
* // onAuthStateChange listeners will now be notified with updated user
|
|
* ```
|
|
*
|
|
* @see {@link GoTrueClient.refreshSession} for syncing admin changes to the client
|
|
* @see {@link GoTrueClient.updateUser} for client-side user updates (triggers listeners automatically)
|
|
*/
|
|
async updateUserById(uid, attributes) {
|
|
(0, helpers_1.validateUUID)(uid);
|
|
try {
|
|
return await (0, fetch_1._request)(this.fetch, 'PUT', `${this.url}/admin/users/${uid}`, {
|
|
body: attributes,
|
|
headers: this.headers,
|
|
xform: fetch_1._userResponse,
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: { user: null }, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Delete a user. Requires a `service_role` key.
|
|
*
|
|
* @param id The user id you want to remove.
|
|
* @param shouldSoftDelete If true, then the user will be soft-deleted from the auth schema. Soft deletion allows user identification from the hashed user ID but is not reversible.
|
|
* Defaults to false for backward compatibility.
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*/
|
|
async deleteUser(id, shouldSoftDelete = false) {
|
|
(0, helpers_1.validateUUID)(id);
|
|
try {
|
|
return await (0, fetch_1._request)(this.fetch, 'DELETE', `${this.url}/admin/users/${id}`, {
|
|
headers: this.headers,
|
|
body: {
|
|
should_soft_delete: shouldSoftDelete,
|
|
},
|
|
xform: fetch_1._userResponse,
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: { user: null }, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
async _listFactors(params) {
|
|
(0, helpers_1.validateUUID)(params.userId);
|
|
try {
|
|
const { data, error } = await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/admin/users/${params.userId}/factors`, {
|
|
headers: this.headers,
|
|
xform: (factors) => {
|
|
return { data: { factors }, error: null };
|
|
},
|
|
});
|
|
return { data, error };
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: null, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
async _deleteFactor(params) {
|
|
(0, helpers_1.validateUUID)(params.userId);
|
|
(0, helpers_1.validateUUID)(params.id);
|
|
try {
|
|
const data = await (0, fetch_1._request)(this.fetch, 'DELETE', `${this.url}/admin/users/${params.userId}/factors/${params.id}`, {
|
|
headers: this.headers,
|
|
});
|
|
return { data, error: null };
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: null, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Lists all OAuth clients with optional pagination.
|
|
* Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*/
|
|
async _listOAuthClients(params) {
|
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
try {
|
|
const pagination = { nextPage: null, lastPage: 0, total: 0 };
|
|
const response = await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/admin/oauth/clients`, {
|
|
headers: this.headers,
|
|
noResolveJson: true,
|
|
query: {
|
|
page: (_b = (_a = params === null || params === void 0 ? void 0 : params.page) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '',
|
|
per_page: (_d = (_c = params === null || params === void 0 ? void 0 : params.perPage) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '',
|
|
},
|
|
xform: fetch_1._noResolveJsonResponse,
|
|
});
|
|
if (response.error)
|
|
throw response.error;
|
|
const clients = await response.json();
|
|
const total = (_e = response.headers.get('x-total-count')) !== null && _e !== void 0 ? _e : 0;
|
|
const links = (_g = (_f = response.headers.get('link')) === null || _f === void 0 ? void 0 : _f.split(',')) !== null && _g !== void 0 ? _g : [];
|
|
if (links.length > 0) {
|
|
links.forEach((link) => {
|
|
const page = parseInt(link.split(';')[0].split('=')[1].substring(0, 1));
|
|
const rel = JSON.parse(link.split(';')[1].split('=')[1]);
|
|
pagination[`${rel}Page`] = page;
|
|
});
|
|
pagination.total = parseInt(total);
|
|
}
|
|
return { data: Object.assign(Object.assign({}, clients), pagination), error: null };
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: { clients: [] }, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Creates a new OAuth client.
|
|
* Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*/
|
|
async _createOAuthClient(params) {
|
|
try {
|
|
return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/admin/oauth/clients`, {
|
|
body: params,
|
|
headers: this.headers,
|
|
xform: (client) => {
|
|
return { data: client, error: null };
|
|
},
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: null, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Gets details of a specific OAuth client.
|
|
* Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*/
|
|
async _getOAuthClient(clientId) {
|
|
try {
|
|
return await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/admin/oauth/clients/${clientId}`, {
|
|
headers: this.headers,
|
|
xform: (client) => {
|
|
return { data: client, error: null };
|
|
},
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: null, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Updates an existing OAuth client.
|
|
* Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*/
|
|
async _updateOAuthClient(clientId, params) {
|
|
try {
|
|
return await (0, fetch_1._request)(this.fetch, 'PUT', `${this.url}/admin/oauth/clients/${clientId}`, {
|
|
body: params,
|
|
headers: this.headers,
|
|
xform: (client) => {
|
|
return { data: client, error: null };
|
|
},
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: null, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Deletes an OAuth client.
|
|
* Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*/
|
|
async _deleteOAuthClient(clientId) {
|
|
try {
|
|
await (0, fetch_1._request)(this.fetch, 'DELETE', `${this.url}/admin/oauth/clients/${clientId}`, {
|
|
headers: this.headers,
|
|
noResolveJson: true,
|
|
});
|
|
return { data: null, error: null };
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: null, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Regenerates the secret for an OAuth client.
|
|
* Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
|
|
*
|
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
*/
|
|
async _regenerateOAuthClientSecret(clientId) {
|
|
try {
|
|
return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/admin/oauth/clients/${clientId}/regenerate_secret`, {
|
|
headers: this.headers,
|
|
xform: (client) => {
|
|
return { data: client, error: null };
|
|
},
|
|
});
|
|
}
|
|
catch (error) {
|
|
if ((0, errors_1.isAuthError)(error)) {
|
|
return { data: null, error };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
exports.default = GoTrueAdminApi;
|
|
//# sourceMappingURL=GoTrueAdminApi.js.map
|