@oxyhq/services
Version:
Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀
299 lines (280 loc) • 7.74 kB
JavaScript
;
/**
* Authentication Methods Mixin
*/
import { OxyAuthenticationError } from '../OxyServices.errors';
export function OxyServicesAuthMixin(Base) {
return class extends Base {
constructor(...args) {
super(...args);
}
/**
* Sign up a new user
*/
async signUp(username, email, password) {
try {
const res = await this.makeRequest('POST', '/api/auth/signup', {
username,
email,
password
}, {
cache: false
});
if (!res || typeof res === 'object' && Object.keys(res).length === 0) {
throw new OxyAuthenticationError('Sign up failed', 'SIGNUP_FAILED', 400);
}
return res;
} catch (error) {
throw this.handleError(error);
}
}
/**
* Request account recovery (send verification code)
*/
async requestRecovery(identifier) {
try {
return await this.makeRequest('POST', '/api/auth/recover/request', {
identifier
}, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Verify recovery code
*/
async verifyRecoveryCode(identifier, code) {
try {
return await this.makeRequest('POST', '/api/auth/recover/verify', {
identifier,
code
}, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Reset password using verified code
*/
async resetPassword(identifier, code, newPassword) {
try {
return await this.makeRequest('POST', '/api/auth/recover/reset', {
identifier,
code,
newPassword
}, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Reset password using TOTP code (recommended recovery)
*/
async resetPasswordWithTotp(identifier, code, newPassword) {
try {
return await this.makeRequest('POST', '/api/auth/recover/totp/reset', {
identifier,
code,
newPassword
}, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
async resetPasswordWithBackupCode(identifier, backupCode, newPassword) {
try {
return await this.makeRequest('POST', '/api/auth/recover/backup/reset', {
identifier,
backupCode,
newPassword
}, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
async resetPasswordWithRecoveryKey(identifier, recoveryKey, newPassword) {
try {
return await this.makeRequest('POST', '/api/auth/recover/recovery-key/reset', {
identifier,
recoveryKey,
newPassword
}, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Sign in with device management
*/
async signIn(username, password, deviceName, deviceFingerprint) {
try {
return await this.makeRequest('POST', '/api/auth/login', {
username,
password,
deviceName,
deviceFingerprint
}, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Complete login by verifying TOTP with MFA token
*/
async verifyTotpLogin(mfaToken, code) {
try {
return await this.makeRequest('POST', '/api/auth/totp/verify-login', {
mfaToken,
code
}, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Get user by session ID
*/
async getUserBySession(sessionId) {
try {
return await this.makeRequest('GET', `/api/session/user/${sessionId}`, undefined, {
cache: true,
cacheTTL: 2 * 60 * 1000 // 2 minutes cache for user data
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Batch get multiple user profiles by session IDs (optimized for account switching)
* Returns array of { sessionId, user } objects
*/
async getUsersBySessions(sessionIds) {
try {
if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
return [];
}
// Deduplicate and sort sessionIds for consistent cache keys
const uniqueSessionIds = Array.from(new Set(sessionIds)).sort();
return await this.makeRequest('POST', '/api/session/users/batch', {
sessionIds: uniqueSessionIds
}, {
cache: true,
cacheTTL: 2 * 60 * 1000,
// 2 minutes cache
deduplicate: true // Important for batch requests
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Get access token by session ID and set it in the token store
*/
async getTokenBySession(sessionId) {
try {
const res = await this.makeRequest('GET', `/api/session/token/${sessionId}`, undefined, {
cache: false,
retry: false
});
// Set the token in the centralized token store
this.setTokens(res.accessToken);
return res;
} catch (error) {
throw this.handleError(error);
}
}
/**
* Get sessions by session ID
*/
async getSessionsBySessionId(sessionId) {
try {
return await this.makeRequest('GET', `/api/session/sessions/${sessionId}`, undefined, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Logout from a specific session
*/
async logoutSession(sessionId, targetSessionId) {
try {
const url = targetSessionId ? `/api/session/logout/${sessionId}/${targetSessionId}` : `/api/session/logout/${sessionId}`;
await this.makeRequest('POST', url, undefined, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Logout from all sessions
*/
async logoutAllSessions(sessionId) {
try {
await this.makeRequest('POST', `/api/session/logout-all/${sessionId}`, undefined, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Validate session
*/
async validateSession(sessionId, options = {}) {
try {
const urlParams = {};
if (options.deviceFingerprint) urlParams.deviceFingerprint = options.deviceFingerprint;
if (options.useHeaderValidation) urlParams.useHeaderValidation = 'true';
return await this.makeRequest('GET', `/api/session/validate/${sessionId}`, urlParams, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Check username availability
*/
async checkUsernameAvailability(username) {
try {
return await this.makeRequest('GET', `/api/auth/check-username/${username}`, undefined, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
/**
* Check email availability
*/
async checkEmailAvailability(email) {
try {
return await this.makeRequest('GET', `/api/auth/check-email/${email}`, undefined, {
cache: false
});
} catch (error) {
throw this.handleError(error);
}
}
};
}
//# sourceMappingURL=OxyServices.auth.js.map