New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@accounts/server

Package Overview
Dependencies
Maintainers
5
Versions
204
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@accounts/server - npm Package Compare versions

Comparing version 0.1.0-alpha.4b98ebbe to 0.1.0-alpha.4d9cf8a2

__tests__/index.ts

1697

__tests__/accounts-server.ts

@@ -1,592 +0,22 @@

import * as jwtDecode from 'jwt-decode';
import { AccountsServer } from '../src/accounts-server';
import {
bcryptPassword,
hashPassword,
verifyPassword,
} from '../src/encryption';
import AccountsServer from '../src/accounts-server';
let Accounts;
describe('AccountsServer', () => {
describe('resumeSession', () => {
const accountsServer = new AccountsServer();
accountsServer.db = {};
describe('Accounts', () => {
const db = {
findUserByUsername: () => Promise.resolve(),
findUserByEmail: () => Promise.resolve(),
createUser: () => Promise.resolve(),
createSession: () => Promise.resolve(),
};
beforeEach(() => {
Accounts = new AccountsServer();
Accounts.config({}, {});
});
describe('hooks', () => {
it('onLoginSuccess', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onLoginSuccess(hookSpy);
Accounts.config(
{
passwordAuthenticator: () => ({}),
},
{
createSession: () => '123',
}
);
await Accounts.loginWithPassword('username', '123456');
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onLoginError with custom authenticator', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onLoginError(hookSpy);
Accounts.config(
{
passwordAuthenticator: () => Promise.reject('error'),
},
{
createSession: () => '123',
}
);
try {
await Accounts.loginWithPassword('username', '123456');
} catch (e) {
// nothing to do
}
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onLoginError with default authenticator', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onLoginError(hookSpy);
Accounts.config(
{},
{
findUserByUsername: () => Promise.resolve('123'),
findUserByEmail: () => Promise.resolve(null),
findPasswordHash: () => Promise.resolve('hash'),
verifyPassword: () => Promise.resolve(false),
}
);
try {
await Accounts.loginWithPassword('username', '123456');
} catch (e) {
// Nothing to do
}
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onCreateUserSuccess', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onCreateUserSuccess(hookSpy);
Accounts.config(
{},
{
...db,
createUser: () => Promise.resolve('123'),
}
);
await Accounts.createUser({
password: '123456',
username: 'user1',
});
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onCreateUserError', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onCreateUserError(hookSpy);
Accounts.config(
{},
{
createUser: () => Promise.reject('err'),
}
);
try {
await Accounts.createUser({
password: '123456',
username: 'user1',
});
} catch (e) {
// nothing to do
}
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onLogoutSuccess', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onLogoutSuccess(hookSpy);
const invalidateSession = jest.fn(() => Promise.resolve());
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
invalidateSession,
}
);
const { accessToken } = Accounts.createTokens('456');
await Accounts.logout(accessToken);
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onLogoutError', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onLogoutError(hookSpy);
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(null),
}
);
try {
const { accessToken } = Accounts.createTokens('456');
await Accounts.logout(accessToken);
} catch (err) {
// nothing to do
}
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onResumeSessionSuccess', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onResumeSessionSuccess(hookSpy);
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{ resumeSessionValidator: () => Promise.resolve(user) },
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
}
);
const { accessToken } = Accounts.createTokens('456');
await Accounts.resumeSession(accessToken);
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onResumeSessionError with invalid session', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onResumeSessionError(hookSpy);
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{ resumeSessionValidator: () => Promise.resolve(user) },
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: false,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
}
);
const { accessToken } = Accounts.createTokens('456');
try {
await Accounts.resumeSession(accessToken);
} catch (e) {
// nothing to do
}
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onResumeSessionError with invalid errored session', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onResumeSessionError(hookSpy);
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{ resumeSessionValidator: () => Promise.resolve(user) },
{
findSessionById: () => Promise.reject(''),
findUserById: () => Promise.resolve(user),
}
);
const { accessToken } = Accounts.createTokens('456');
try {
await Accounts.resumeSession(accessToken);
} catch (e) {
// nothing to do
}
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onRefreshTokenError', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onRefreshTokensError(hookSpy);
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
valid: false,
}),
}
);
try {
const { accessToken, refreshToken } = Accounts.createTokens();
await Accounts.refreshTokens(accessToken, refreshToken);
} catch (err) {
// nothing to do
}
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onRefreshTokenSuccess', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onRefreshTokensSuccess(hookSpy);
const updateSession = () => Promise.resolve();
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
updateSession,
}
);
const { accessToken, refreshToken } = Accounts.createTokens('456');
Accounts.createTokens = () => ({
accessToken: 'newAccessToken',
refreshToken: 'newRefreshToken',
});
await Accounts.refreshTokens(
accessToken,
refreshToken,
'ip',
'user agent'
);
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onImpersonationError', async () => {
const hookSpy = jest.fn(() => null);
Accounts.onImpersonationError(hookSpy);
Accounts.config({}, db);
try {
await Accounts.impersonate();
} catch (err) {
// nothing to do
}
expect(hookSpy.mock.calls.length).toBe(1);
});
it('onImpersonationSuccess', async () => {
const user = { username: 'myUser', id: 123 };
const impersonatedUser = { username: 'impUser', id: 456 };
const { accessToken } = Accounts.createTokens('555');
const hookSpy = jest.fn(() => null);
Accounts.onImpersonationSuccess(hookSpy);
Accounts.config(
{
impersonationAuthorize: async (userObject, impersonateToUser) => {
return (
userObject.id === user.id &&
impersonateToUser === impersonatedUser
);
},
},
{
findUserById: () => Promise.resolve(user),
findUserByUsername: () => Promise.resolve(impersonatedUser),
createSession: () => Promise.resolve('001'),
}
);
Accounts.findSessionByAccessToken = () =>
it('throws error if user is not found', async () => {
accountsServer.db.findSessionById = () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
});
Accounts.createTokens = (sessionId, isImpersonated) => ({
sessionId,
isImpersonated,
});
await Accounts.impersonate(accessToken, 'impUser');
expect(hookSpy.mock.calls.length).toBe(1);
});
});
describe('config', () => {
it('requires a db driver', () => {
accountsServer.db.findUserById = () => Promise.resolve(null);
try {
Accounts.config();
const { accessToken } = accountsServer.createTokens('456');
await accountsServer.resumeSession(accessToken);
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('A database driver is required');
}
});
it('sets the db driver', () => {
const testDB = {};
Accounts.config({}, testDB);
expect(Accounts.db).toEqual(testDB);
});
it('set custom password authenticator', () => {
const testDB = {};
Accounts.config({ passwordAuthenticator: () => null }, testDB);
expect(Accounts._options.passwordAuthenticator).toBeDefined();
});
it('set custom userObjectSanitizer', () => {
const testDB = {};
const func = () => null;
Accounts.config({ userObjectSanitizer: func }, testDB);
expect(Accounts._options.userObjectSanitizer).toBe(func);
});
it('use default password authenticator', () => {
const testDB = {};
Accounts.config({}, testDB);
expect(Accounts._options.passwordAuthenticator).toBeUndefined();
});
it('override allowedLoginFields values', () => {
const testDB = {};
Accounts.config({ allowedLoginFields: ['id'] }, testDB);
expect(Accounts._options.allowedLoginFields).toEqual(['id']);
});
it('default allowedLoginFields values', () => {
const testDB = {};
Accounts.config({}, testDB);
expect(Accounts._options.allowedLoginFields).toEqual([
'id',
'email',
'username',
]);
});
});
describe('options', () => {
it('should return options', () => {
Accounts.config({ config: 'config' }, {});
const options = Accounts.options();
expect(options.config).toEqual('config');
});
});
describe('createUser', () => {
beforeEach(() => {
Accounts.config({}, db);
});
it('requires username or an email', async () => {
Accounts.config({}, db);
try {
await Accounts.createUser({
password: '123456',
username: '',
email: '',
});
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('Username or Email is required');
}
});
it('throws error if username exists', async () => {
Accounts.config(
{},
{
...db,
findUserByUsername: () => Promise.resolve('user'),
}
);
try {
await Accounts.createUser({
password: '123456',
username: 'user1',
email: '',
});
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('Username already exists');
}
});
it('throws error if email exists', async () => {
Accounts.config(
{},
{
...db,
findUserByEmail: () => Promise.resolve('user'),
}
);
try {
await Accounts.createUser({
password: '123456',
username: '',
email: 'email1@email.com',
});
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('Email already exists');
}
});
it('succesfully create a user', async () => {
Accounts.config(
{},
{
...db,
createUser: () => Promise.resolve('123'),
}
);
const userId = await Accounts.createUser({
password: '123456',
username: 'user1',
});
expect(userId).toEqual('123');
});
it('throws error if validateNewUser does not pass', async () => {
Accounts.config(
{
validateNewUser: () => Promise.reject('User did not pass validation'),
},
{
...db,
createUser: () => Promise.resolve('123'),
}
);
try {
await Accounts.createUser({
password: '123456',
username: 'user1',
});
throw Error();
} catch (err) {
expect(err).toEqual('User did not pass validation');
}
});
});
describe('loginWithPassword - errors', () => {
it('throws error if user is undefined', async () => {
try {
await Accounts.loginWithPassword(null, '123456');
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('Unrecognized options for login request');
}
});
it('throws error if password is undefined', async () => {
try {
await Accounts.loginWithPassword('username', null);
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('Unrecognized options for login request');
}
});
it('throws error if user is not a string or an object', async () => {
try {
await Accounts.loginWithPassword(1, '123456');
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('Match failed');
}
});
it('throws error if password is not a string', async () => {
try {
await Accounts.loginWithPassword('username', {});
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('Match failed');
}
});
it('throws error if user is not found', async () => {
Accounts.config(
{},
{
findUserByUsername: () => Promise.resolve(null),
findUserByEmail: () => Promise.resolve(null),
}
);
try {
await Accounts.loginWithPassword('username', '123456');
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('User not found');

@@ -596,89 +26,20 @@ }

it('throws error if password not set', async () => {
Accounts.config(
{},
{
findUserByUsername: () => Promise.resolve('123'),
findUserByEmail: () => Promise.resolve(null),
findPasswordHash: () => Promise.resolve(null),
}
);
try {
await Accounts.loginWithPassword('username', '123456');
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('User has no password set');
}
});
it('throws error if password is incorrect', async () => {
Accounts.config(
{},
{
findUserByUsername: () => Promise.resolve('123'),
findUserByEmail: () => Promise.resolve(null),
findPasswordHash: () => Promise.resolve('hash'),
verifyPassword: () => Promise.resolve(false),
}
);
try {
await Accounts.loginWithPassword('username', '123456');
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('Incorrect password');
}
});
it('should use custom password authenticator when specified', async () => {
it('return false if session is not valid', async () => {
const user = {
id: '123',
username: 'username',
email: 'email@email.com',
profile: {
bio: 'bio',
},
};
const authenticator = jest.fn(() => Promise.resolve(user));
Accounts.config({ passwordAuthenticator: authenticator }, db);
const result = await Accounts.loginWithPassword('username', '123456');
expect(result).toBeDefined();
expect(authenticator.mock.calls.length).toEqual(1);
});
it('return user with custom validation method', async () => {
const resumeSessionValidator = jest.fn(() => Promise.resolve({}));
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{ resumeSessionValidator },
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
}
);
const { accessToken } = Accounts.createTokens('456');
await Accounts.resumeSession(accessToken);
expect(resumeSessionValidator.mock.calls.length).toBe(1);
accountsServer.db.findSessionById = () =>
Promise.resolve({
sessionId: '456',
valid: false,
userId: '123',
});
accountsServer.db.findUserById = () => Promise.resolve(user);
const { accessToken } = accountsServer.createTokens('456');
const ret = await accountsServer.resumeSession(accessToken);
expect(ret).not.toBeTruthy();
});
it('throw when custom validation method rejects', async () => {
const resumeSessionValidator = jest.fn(() =>
Promise.reject('Custom session error')
);
it('return user', async () => {
const user = {

@@ -688,200 +49,31 @@ userId: '123',

};
Accounts.config(
{ resumeSessionValidator },
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
}
);
const { accessToken } = Accounts.createTokens('456');
try {
await Accounts.resumeSession(accessToken);
throw new Error();
} catch (err) {
expect(resumeSessionValidator.mock.calls.length).toBe(1);
expect(err.message).toEqual('Custom session error');
}
accountsServer.db.findSessionById = () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
});
accountsServer.db.findUserById = () => Promise.resolve(user);
const { accessToken } = accountsServer.createTokens('456');
const foundUser = await accountsServer.resumeSession(accessToken);
expect(foundUser).toEqual(user);
});
});
describe('loginWithUser', () => {
it('login using id', async () => {
const hash = bcryptPassword('1234567');
const user = {
id: '123',
username: 'username',
email: 'email@email.com',
profile: {
bio: 'bio',
},
};
const findUserById = jest.fn(() => Promise.resolve(user));
Accounts.config(
{},
{
findUserById,
findPasswordHash: () => Promise.resolve(hash),
createSession: () => Promise.resolve('sessionId'),
}
);
const res = await Accounts.loginWithPassword({ id: '123' }, '1234567');
expect(findUserById.mock.calls[0][0]).toEqual('123');
expect(res.user).toEqual(user);
const { accessToken, refreshToken } = res.tokens;
const decodedAccessToken = jwtDecode(accessToken);
expect(decodedAccessToken.data.sessionId).toEqual('sessionId');
expect(accessToken).toBeTruthy();
expect(refreshToken).toBeTruthy();
});
describe('findSessionByAccessToken', () => {
const accountsServer = new AccountsServer();
accountsServer.db = {};
it('try to login using id and password when id login is not allowed', async () => {
const hash = bcryptPassword('1234567');
const user = {
id: '123',
username: 'username',
email: 'email@email.com',
profile: {
bio: 'bio',
},
};
const findUserById = jest.fn(() => Promise.resolve(user));
Accounts.config(
{
allowedLoginFields: ['email'],
},
{
findUserById,
findPasswordHash: () => Promise.resolve(hash),
createSession: () => Promise.resolve('sessionId'),
}
);
it('requires access token', async () => {
try {
await Accounts.loginWithPassword({ id: '123' }, '1234567');
await accountsServer.findSessionByAccessToken();
throw new Error();
} catch (err) {
expect(err.message).toEqual('Login with id is not allowed!');
expect(err.message).toEqual('An accessToken is required');
}
});
it('try to login using id and password when id login only is allowed ', async () => {
const hash = bcryptPassword('1234567');
const user = {
id: '123',
username: 'username',
email: 'email@email.com',
profile: {
bio: 'bio',
},
};
const findUserById = jest.fn(() => Promise.resolve(user));
Accounts.config(
{
allowedLoginFields: ['id'],
},
{
findUserById,
findPasswordHash: () => Promise.resolve(hash),
createSession: () => Promise.resolve('sessionId'),
}
);
const res = await Accounts.loginWithPassword({ id: '123' }, '1234567');
expect(res).toBeDefined();
});
it('supports hashed password from the client', async () => {
const hash = bcryptPassword(hashPassword('1234567', 'sha256'));
const user = {
id: '123',
username: 'username',
email: 'email@email.com',
profile: {
bio: 'bio',
},
};
const findUserById = jest.fn(() => Promise.resolve(user));
Accounts.config(
{
passwordHashAlgorithm: 'sha256',
},
{
findUserById,
findPasswordHash: () => Promise.resolve(hash),
createSession: () => Promise.resolve('sessionId'),
}
);
const res = await Accounts.loginWithPassword({ id: '123' }, '1234567');
expect(findUserById.mock.calls[0][0]).toEqual('123');
expect(res.user).toEqual(user);
const { accessToken, refreshToken } = res.tokens;
const decodedAccessToken = jwtDecode(accessToken);
expect(decodedAccessToken.data.sessionId).toEqual('sessionId');
expect(accessToken).toBeTruthy();
expect(refreshToken).toBeTruthy();
});
});
describe('refreshTokens', () => {
it('updates session and returns new tokens and user', async () => {
const updateSession = jest.fn(() => Promise.resolve());
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
updateSession,
}
);
const { accessToken, refreshToken } = Accounts.createTokens('456');
Accounts.createTokens = () => ({
accessToken: 'newAccessToken',
refreshToken: 'newRefreshToken',
});
const res = await Accounts.refreshTokens(
accessToken,
refreshToken,
'ip',
'user agent'
);
expect(updateSession.mock.calls[0]).toEqual(['456', 'ip', 'user agent']);
expect(res.user).toEqual({
userId: '123',
username: 'username',
});
});
it('requires access and refresh tokens', async () => {
Accounts.config({}, {});
try {
await Accounts.refreshTokens();
throw new Error();
} catch (err) {
expect(err.message).toEqual(
'An accessToken and refreshToken are required'
);
}
});
it('throws error if tokens are not valid', async () => {
Accounts.config({}, {});
try {
await Accounts.refreshTokens('bad access token', 'bad refresh token');
await accountsServer.findSessionByAccessToken('bad access token');
throw new Error();

@@ -892,115 +84,8 @@ } catch (err) {

});
it('throws error if session not found', async () => {
Accounts.config(
{},
{
findSessionById: () => Promise.resolve(null),
}
);
try {
const { accessToken, refreshToken } = Accounts.createTokens();
await Accounts.refreshTokens(accessToken, refreshToken);
throw new Error();
} catch (err) {
expect(err.message).toEqual('Session not found');
}
});
it('throws error if session not valid', async () => {
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
valid: false,
}),
}
);
try {
const { accessToken, refreshToken } = Accounts.createTokens();
await Accounts.refreshTokens(accessToken, refreshToken);
throw new Error();
} catch (err) {
expect(err.message).toEqual('Session is no longer valid');
}
});
});
describe('logout', () => {
it('throws error if user is not found', async () => {
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(null),
}
);
try {
const { accessToken } = Accounts.createTokens('456');
await Accounts.logout(accessToken);
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('User not found');
}
});
it('invalidates session', async () => {
const invalidateSession = jest.fn(() => Promise.resolve());
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
invalidateSession,
}
);
const { accessToken } = Accounts.createTokens('456');
await Accounts.logout(accessToken);
expect(invalidateSession.mock.calls[0]).toEqual(['456']);
});
});
describe('findSessionByAccessToken', () => {
it('requires access token', async () => {
Accounts.config({}, {});
try {
await Accounts.logout();
throw new Error();
} catch (err) {
expect(err.message).toEqual('An accessToken is required');
}
});
it('throws error if tokens are not valid', async () => {
Accounts.config({}, {});
try {
await Accounts.logout('bad access token');
throw new Error();
} catch (err) {
expect(err.message).toEqual('Tokens are not valid');
}
});
it('throws error if session not found', async () => {
Accounts.config(
{},
{
findSessionById: () => Promise.resolve(null),
}
);
accountsServer.db.findSessionById = () => Promise.resolve(null);
try {
const { accessToken } = Accounts.createTokens();
await Accounts.logout(accessToken);
const { accessToken } = accountsServer.createTokens();
await accountsServer.findSessionByAccessToken(accessToken);
throw new Error();

@@ -1011,695 +96,31 @@ } catch (err) {

});
it('throws error if session not valid', async () => {
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
valid: false,
}),
}
);
try {
const { accessToken } = Accounts.createTokens();
await Accounts.logout(accessToken);
throw new Error();
} catch (err) {
expect(err.message).toEqual('Session is no longer valid');
}
});
});
describe('findUserByEmail', () => {
it('call this.db.findUserByEmail', async () => {
const findUserByEmail = jest.fn(() => Promise.resolve('user'));
Accounts.config({}, { findUserByEmail });
const user = await Accounts.findUserByEmail('email');
expect(findUserByEmail.mock.calls[0]).toEqual(['email']);
expect(user).toEqual('user');
});
});
describe('findUserByUsername', () => {
it('call this.db.findUserByUsername', async () => {
const findUserByUsername = jest.fn(() => Promise.resolve('user'));
Accounts.config({}, { findUserByUsername });
const user = await Accounts.findUserByUsername('username');
expect(findUserByUsername.mock.calls[0]).toEqual(['username']);
expect(user).toEqual('user');
});
});
describe('findUserById', () => {
it('call this.db.findUserById', async () => {
const findUserById = jest.fn(() => Promise.resolve('user'));
Accounts.config({}, { findUserById });
const user = await Accounts.findUserById('id');
expect(findUserById.mock.calls[0]).toEqual(['id']);
expect(user).toEqual('user');
});
});
describe('addEmail', () => {
it('call this.db.addEmail', async () => {
const addEmail = jest.fn(() => Promise.resolve());
Accounts.config({}, { addEmail });
await Accounts.addEmail('id', 'email', true);
expect(addEmail.mock.calls[0]).toEqual(['id', 'email', true]);
});
});
describe('removeEmail', () => {
it('call this.db.removeEmail', async () => {
const removeEmail = jest.fn(() => Promise.resolve());
Accounts.config({}, { removeEmail });
await Accounts.removeEmail('id', 'email');
expect(removeEmail.mock.calls[0]).toEqual(['id', 'email']);
});
});
describe('resumeSession', () => {
it('throws error if user is not found', async () => {
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(null),
}
it('find the session', async () => {
const sessionReturn = { a: 'a' };
accountsServer.db.findSessionById = () => Promise.resolve(sessionReturn);
const { accessToken } = accountsServer.createTokens();
const session = await accountsServer.findSessionByAccessToken(
accessToken
);
try {
const { accessToken } = Accounts.createTokens('456');
await Accounts.resumeSession(accessToken);
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('User not found');
}
expect(session).toEqual(sessionReturn);
});
it('return false if session is not valid', async () => {
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: false,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
}
);
const { accessToken } = Accounts.createTokens('456');
const ret = await Accounts.resumeSession(accessToken);
expect(ret).not.toBeTruthy();
});
it('return user', async () => {
const user = {
userId: '123',
username: 'username',
};
Accounts.config(
{},
{
findSessionById: () =>
Promise.resolve({
sessionId: '456',
valid: true,
userId: '123',
}),
findUserById: () => Promise.resolve(user),
}
);
const { accessToken } = Accounts.createTokens('456');
const foundUser = await Accounts.resumeSession(accessToken);
expect(foundUser).toEqual(user);
});
});
describe('setProfile', () => {
it('throws error if user is not found', async () => {
Accounts.config(
{},
{
findUserById: () => Promise.resolve(null),
}
);
try {
await Accounts.setProfile();
throw new Error();
} catch (err) {
const { message } = err;
expect(message).toEqual('User not found');
}
describe('createTokens', () => {
const accountsServer = new AccountsServer();
it('should create tokens', () => {
const tokens = accountsServer.createTokens('a');
expect(tokens.accessToken).toBeTruthy();
expect(tokens.refreshToken).toBeTruthy();
});
it('calls set profile on db interface', async () => {
const user = {
userId: '123',
username: 'username',
};
const profile = {
bio: 'bio',
};
const setProfile = jest.fn();
Accounts.config(
{},
{
findUserById: () => Promise.resolve(user),
setProfile,
}
);
await Accounts.setProfile('123', profile);
expect(setProfile.mock.calls.length).toEqual(1);
expect(setProfile.mock.calls[0][0]).toEqual('123');
expect(setProfile.mock.calls[0][1]).toEqual(profile);
});
it('merges profile and calls set profile on db interface', async () => {
const user = {
userId: '123',
username: 'username',
profile: {
title: 'title',
},
};
const profile = {
bio: 'bio',
};
const mergedProfile = {
title: 'title',
bio: 'bio',
};
const setProfile = jest.fn(() => mergedProfile);
Accounts.config(
{},
{
findUserById: () => Promise.resolve(user),
setProfile,
}
);
const res = await Accounts.updateProfile('123', profile);
expect(setProfile.mock.calls.length).toEqual(1);
expect(setProfile.mock.calls[0][0]).toEqual('123');
expect(setProfile.mock.calls[0][1]).toEqual(mergedProfile);
expect(res).toEqual(mergedProfile);
});
});
describe('sendVerificationEmail', () => {
it('throws error if user is not found', async () => {
Accounts.config(
{},
{
findUserByEmail: () => Promise.resolve(null),
}
);
try {
await Accounts.sendVerificationEmail();
throw new Error();
} catch (err) {
expect(err.message).toEqual('User not found');
}
});
it('throws when bad email address passed', async () => {
const user = {
emails: [{ address: 'email' }],
};
Accounts.config(
{},
{
findUserByEmail: () => Promise.resolve(user),
}
);
try {
await Accounts.sendVerificationEmail('toto');
throw new Error();
} catch (err) {
expect(err.message).toEqual('No such email address for user');
}
});
it('should send to first unverified email', async () => {
const user = {
emails: [{ address: 'email' }],
};
Accounts.config(
{},
{
findUserByEmail: () => Promise.resolve(user),
addEmailVerificationToken: () => Promise.resolve('token'),
}
);
Accounts.email = { sendMail: jest.fn() };
await Accounts.sendVerificationEmail('email');
expect(Accounts.email.sendMail.mock.calls.length).toEqual(1);
expect(Accounts.email.sendMail.mock.calls[0][0].from).toBeTruthy();
expect(Accounts.email.sendMail.mock.calls[0][0].to).toEqual('email');
expect(Accounts.email.sendMail.mock.calls[0][0].subject).toBeTruthy();
expect(Accounts.email.sendMail.mock.calls[0][0].text).toBeTruthy();
});
it('should send email', async () => {
const user = {
emails: [{ address: 'email' }],
};
Accounts.config(
{},
{
findUserByEmail: () => Promise.resolve(user),
addEmailVerificationToken: () => Promise.resolve('token'),
}
);
Accounts.email = { sendMail: jest.fn() };
await Accounts.sendVerificationEmail('email');
expect(Accounts.email.sendMail.mock.calls.length).toEqual(1);
expect(Accounts.email.sendMail.mock.calls[0][0].from).toBeTruthy();
expect(Accounts.email.sendMail.mock.calls[0][0].to).toEqual('email');
expect(Accounts.email.sendMail.mock.calls[0][0].subject).toBeTruthy();
expect(Accounts.email.sendMail.mock.calls[0][0].text).toBeTruthy();
});
});
describe('sendResetPasswordEmail', () => {
it('throws error if user is not found', async () => {
Accounts.config(
{},
{
findUserByEmail: () => Promise.resolve(null),
}
);
try {
await Accounts.sendResetPasswordEmail();
throw new Error();
} catch (err) {
expect(err.message).toEqual('User not found');
}
});
it('throws when bad email address passed', async () => {
const user = {
emails: [{ address: 'email' }],
};
Accounts.config(
{},
{
findUserByEmail: () => Promise.resolve(user),
}
);
try {
await Accounts.sendResetPasswordEmail('toto');
throw new Error();
} catch (err) {
expect(err.message).toEqual('No such email address for user');
}
});
it('should send to first user email', async () => {
const user = {
emails: [{ address: 'email' }],
};
Accounts.config(
{},
{
findUserByEmail: () => Promise.resolve(user),
addResetPasswordToken: () => Promise.resolve('token'),
}
);
Accounts.email = { sendMail: jest.fn() };
await Accounts.sendResetPasswordEmail('email');
expect(Accounts.email.sendMail.mock.calls.length).toEqual(1);
expect(Accounts.email.sendMail.mock.calls[0][0].from).toBeTruthy();
expect(Accounts.email.sendMail.mock.calls[0][0].to).toEqual('email');
expect(Accounts.email.sendMail.mock.calls[0][0].subject).toBeTruthy();
expect(Accounts.email.sendMail.mock.calls[0][0].text).toBeTruthy();
});
it('should send email', async () => {
const user = {
emails: [{ address: 'email' }],
};
Accounts.config(
{},
{
findUserByEmail: () => Promise.resolve(user),
addResetPasswordToken: () => Promise.resolve('token'),
}
);
Accounts.email = { sendMail: jest.fn() };
await Accounts.sendResetPasswordEmail('email');
expect(Accounts.email.sendMail.mock.calls.length).toEqual(1);
expect(Accounts.email.sendMail.mock.calls[0][0].from).toBeTruthy();
expect(Accounts.email.sendMail.mock.calls[0][0].to).toEqual('email');
expect(Accounts.email.sendMail.mock.calls[0][0].subject).toBeTruthy();
expect(Accounts.email.sendMail.mock.calls[0][0].text).toBeTruthy();
});
});
describe('resetPassword', () => {
it('should reset the password and invalidate all sessions', async () => {
const user = {
id: 'userId',
emails: [{ address: 'email' }],
services: {
password: {
reset: [
{
token: 'token',
address: 'email',
when: Date.now(),
reason: 'reset',
},
],
},
},
};
const setResetPassswordMock = jest.fn(() => Promise.resolve());
const invalidateAllSessionsMock = jest.fn();
Accounts.config(
{},
{
findUserByResetPasswordToken: () => Promise.resolve(user),
setResetPasssword: setResetPassswordMock,
invalidateAllSessions: invalidateAllSessionsMock,
}
);
await Accounts.resetPassword('token', 'password');
expect(setResetPassswordMock.mock.calls.length).toEqual(1);
expect(setResetPassswordMock.mock.calls[0][0]).toEqual('userId');
expect(setResetPassswordMock.mock.calls[0][1]).toEqual('email');
const hashPass = setResetPassswordMock.mock.calls[0][2];
expect(await verifyPassword('password', hashPass)).toBeTruthy();
expect(setResetPassswordMock.mock.calls[0][3]).toEqual('token');
expect(invalidateAllSessionsMock.mock.calls.length).toEqual(1);
expect(invalidateAllSessionsMock.mock.calls[0]).toEqual(['userId']);
});
it('throws when token was not found', async () => {
const setResetPassswordMock = jest.fn(() => Promise.resolve());
const invalidateAllSessionsMock = jest.fn();
Accounts.config(
{},
{
findUserByResetPasswordToken: () => Promise.resolve(null),
setResetPasssword: setResetPassswordMock,
invalidateAllSessions: invalidateAllSessionsMock,
}
);
try {
await Accounts.resetPassword('token', 'password');
throw new Error();
} catch (e) {
expect(e.message).toEqual('Reset password link expired');
expect(setResetPassswordMock.mock.calls.length).toEqual(0);
expect(invalidateAllSessionsMock.mock.calls.length).toEqual(0);
}
});
it('throws if token expired', async () => {
const user = {
id: 'userId',
emails: [{ address: 'email' }],
services: {
password: {
reset: [
{
token: 'token',
address: 'email',
when: 0,
reason: 'reset',
},
],
},
},
};
const setResetPassswordMock = jest.fn(() => Promise.resolve());
const invalidateAllSessionsMock = jest.fn();
Accounts.config(
{},
{
findUserByResetPasswordToken: () => Promise.resolve(user),
setResetPasssword: setResetPassswordMock,
invalidateAllSessions: invalidateAllSessionsMock,
}
);
try {
await Accounts.resetPassword('token', 'password');
throw new Error();
} catch (e) {
expect(e.message).toEqual('Reset password link expired');
expect(setResetPassswordMock.mock.calls.length).toEqual(0);
expect(invalidateAllSessionsMock.mock.calls.length).toEqual(0);
}
});
it('throws if emails mismatch for some reason', async () => {
const user = {
id: 'userId',
emails: [{ address: 'email' }],
services: {
password: {
reset: [
{
token: 'token',
address: 'email2',
when: Date.now(),
reason: 'reset',
},
],
},
},
};
const setResetPassswordMock = jest.fn(() => Promise.resolve());
const invalidateAllSessionsMock = jest.fn();
Accounts.config(
{},
{
findUserByResetPasswordToken: () => Promise.resolve(user),
setResetPasssword: setResetPassswordMock,
invalidateAllSessions: invalidateAllSessionsMock,
}
);
try {
await Accounts.resetPassword('token', 'password');
throw new Error();
} catch (e) {
expect(e.message).toEqual('Token has invalid email address');
expect(setResetPassswordMock.mock.calls.length).toEqual(0);
expect(invalidateAllSessionsMock.mock.calls.length).toEqual(0);
}
});
});
describe('sendEnrollmentEmail', () => {
it('throws error if user not found', async () => {
Accounts.config(
{},
{
findUserByEmail: () => Promise.resolve(null),
}
);
try {
await Accounts.sendEnrollmentEmail('email');
throw new Error();
} catch (err) {
expect(err.message).toEqual('User not found');
}
});
it('adds email verification token and sends mail', async () => {
const addResetPasswordToken = jest.fn();
const getFirstUserEmail = jest.fn(() => 'user@user.com');
const sendMail = jest.fn();
Accounts.config(
{
siteUrl: 'siteUrl',
},
{
findUserByEmail: () =>
Promise.resolve({
id: 'userId',
emails: [
{
address: 'user@user.com',
verified: false,
},
],
}),
addResetPasswordToken,
}
);
Accounts._getFirstUserEmail = getFirstUserEmail;
Accounts.email.sendMail = sendMail;
await Accounts.sendEnrollmentEmail('user@user.com');
expect(addResetPasswordToken.mock.calls[0][0]).toEqual('userId');
expect(addResetPasswordToken.mock.calls[0][1]).toEqual('user@user.com');
expect(addResetPasswordToken.mock.calls[0][3]).toEqual('enroll');
expect(sendMail.mock.calls.length).toEqual(1);
});
});
describe('_getFirstUserEmail', () => {
it('throws error if email does not exist', () => {
try {
Accounts._getFirstUserEmail({
emails: [
{
address: '',
verified: false,
},
],
});
throw new Error();
} catch (err) {
expect(err.message).toEqual('No such email address for user');
}
try {
Accounts._getFirstUserEmail(
{
emails: [
{
address: 'wrongemail@email.com',
verified: false,
},
],
},
'email'
);
throw new Error();
} catch (err) {
expect(err.message).toEqual('No such email address for user');
}
});
it('returns first email', () => {
const email = Accounts._getFirstUserEmail({
emails: [
{
address: 'email@email.com',
verified: false,
},
{
address: 'another@email.com',
verified: false,
},
],
});
expect(email).toEqual('email@email.com');
});
});
describe('impersonate', () => {
const user = { username: 'myUser', id: 123 };
const impersonatedUser = { username: 'impUser', id: 456 };
const someUser = { username: 'someUser', id: 789 };
it('throws error if no access token is provided', async () => {
Accounts.config({}, db);
try {
await Accounts.impersonate();
throw new Error();
} catch (err) {
expect(err.message).toEqual('An access token is required');
}
});
it('returns not authorized if impersonationAuthorize function is not passed in config', async () => {
const { accessToken } = Accounts.createTokens('555');
Accounts.config(
{
impersonationAuthorize: async (userObject, impersonateToUser) => {
return (
userObject.id === user.id &&
impersonateToUser === impersonatedUser
);
},
},
{
findUserById: () => Promise.resolve(user),
findUserByUsername: () => Promise.resolve(someUser),
}
);
Accounts.findSessionByAccessToken = () =>
Promise.resolve({
valid: true,
userId: '123',
});
const impersonationAuthorize = Accounts.options().impersonationAuthorize;
expect(impersonationAuthorize).toBeDefined();
const res = await Accounts.impersonate(accessToken, 'someUser');
expect(res.authorized).toEqual(false);
});
it('returns correct response if authorized', async () => {
const { accessToken } = Accounts.createTokens('555');
Accounts.config(
{
impersonationAuthorize: async (userObject, impersonateToUser) => {
return (
userObject.id === user.id &&
impersonateToUser === impersonatedUser
);
},
},
{
findUserById: () => Promise.resolve(user),
findUserByUsername: () => Promise.resolve(impersonatedUser),
createSession: () => Promise.resolve('001'),
}
);
Accounts.findSessionByAccessToken = () =>
Promise.resolve({
valid: true,
userId: '123',
});
Accounts.createTokens = (sessionId, isImpersonated) => ({
sessionId,
isImpersonated,
});
const res = await Accounts.impersonate(accessToken, 'impUser');
expect(res).toEqual({
authorized: true,
tokens: { sessionId: '001', isImpersonated: true },
user: impersonatedUser,
});
});
});
describe('user sanitizer', () => {
describe('sanitizeUser', () => {
const accountsServer = new AccountsServer();
const userObject = { username: 'test', services: [], id: '123' };
it('internal sanitizer should clean services field from the user object', () => {
Accounts.config({}, db);
const modifiedUser = Accounts._sanitizeUser(userObject);
const modifiedUser = accountsServer.sanitizeUser(userObject);
expect(modifiedUser.services).toBeUndefined();
});
it('should run external sanitizier when provided one', () => {
Accounts.config(
{
userObjectSanitizer: (user, omit) => omit(user, ['username']),
},
db
);
const modifiedUser = Accounts._sanitizeUser(userObject);
expect(modifiedUser.username).toBeUndefined();
});
});
});

@@ -1,83 +0,26 @@

/// <reference types="@types/node" />
import { EventEmitter } from 'events';
import { UserObjectType, CreateUserType, PasswordLoginUserType, LoginReturnType, TokensType, SessionType, ImpersonateReturnType, PasswordType, HookListener } from '@accounts/common';
import { AccountsServerConfiguration, PasswordAuthenticator } from './config';
import { DBInterface } from './db-interface';
export interface TokenRecord {
token: string;
address: string;
when: number;
reason: string;
import { UserObjectType, LoginReturnType } from '@accounts/common';
import { ConnectionInformationsType, DBInterface } from './types';
export interface AccountsServerOptions {
db: DBInterface;
tokenSecret: string;
tokenConfigs?: {
accessToken?: {
expiresIn?: string;
};
refreshToken?: {
expiresIn?: string;
};
};
}
export declare type RemoveListnerHandle = () => EventEmitter;
export declare const ServerHooks: {
LoginSuccess: string;
LoginError: string;
LogoutSuccess: string;
LogoutError: string;
CreateUserSuccess: string;
CreateUserError: string;
ResumeSessionSuccess: string;
ResumeSessionError: string;
RefreshTokensSuccess: string;
RefreshTokensError: string;
ImpersonationSuccess: string;
ImpersonationError: string;
};
export declare class AccountsServer {
private _options;
export default class AccountsServer {
private services;
private db;
private email;
private emailTemplates;
private hooks;
config(options: AccountsServerConfiguration, db: DBInterface): void;
options(): AccountsServerConfiguration;
onLoginSuccess(callback: HookListener): RemoveListnerHandle;
onLoginError(callback: HookListener): RemoveListnerHandle;
onLogoutSuccess(callback: HookListener): RemoveListnerHandle;
onLogoutError(callback: HookListener): RemoveListnerHandle;
onCreateUserSuccess(callback: HookListener): RemoveListnerHandle;
onCreateUserError(callback: HookListener): RemoveListnerHandle;
onResumeSessionSuccess(callback: HookListener): RemoveListnerHandle;
onResumeSessionError(callback: HookListener): RemoveListnerHandle;
onRefreshTokensSuccess(callback: HookListener): RemoveListnerHandle;
onRefreshTokensError(callback: HookListener): RemoveListnerHandle;
onImpersonationSuccess(callback: HookListener): RemoveListnerHandle;
onImpersonationError(callback: HookListener): RemoveListnerHandle;
loginWithPassword(user: PasswordLoginUserType, password: PasswordType, ip: string, userAgent: string): Promise<LoginReturnType>;
_externalPasswordAuthenticator(authFn: PasswordAuthenticator, user: PasswordLoginUserType, password: PasswordType): Promise<any>;
loginWithUser(user: UserObjectType, ip?: string, userAgent?: string): Promise<LoginReturnType>;
createUser(user: CreateUserType): Promise<string>;
impersonate(accessToken: string, username: string, ip: string, userAgent: string): Promise<ImpersonateReturnType>;
refreshTokens(accessToken: string, refreshToken: string, ip: string, userAgent: string): Promise<LoginReturnType>;
createTokens(sessionId: string, isImpersonated?: boolean): TokensType;
logout(accessToken: string): Promise<void>;
resumeSession(accessToken: string): Promise<UserObjectType>;
findSessionByAccessToken(accessToken: string): Promise<SessionType>;
findUserByEmail(email: string): Promise<UserObjectType>;
findUserByUsername(username: string): Promise<UserObjectType>;
findUserById(userId: string): Promise<UserObjectType>;
addEmail(userId: string, newEmail: string, verified: boolean): Promise<void>;
removeEmail(userId: string, email: string): Promise<void>;
verifyEmail(token: string): Promise<void>;
resetPassword(token: string, newPassword: PasswordType): Promise<void>;
setPassword(userId: string, newPassword: string): Promise<void>;
setProfile(userId: string, profile: object): Promise<void>;
updateProfile(userId: string, profile: object): Promise<object>;
sendVerificationEmail(address: string): Promise<void>;
sendResetPasswordEmail(address: string): Promise<void>;
sendEnrollmentEmail(address: string): Promise<void>;
private _on(eventName, callback);
private _isTokenExpired(token, tokenRecord?);
private _internalUserSanitizer(user);
private _sanitizeUser(user);
private _prepareMail(to, token, user, pathFragment, emailTemplate, from);
private _defaultPrepareEmail(to, token, user, pathFragment, emailTemplate, from);
private _defaultCreateTokenizedUrl(pathFragment, token);
private _getFirstUserEmail(user, address);
private _hashAndBcryptPassword(password);
private _validateLoginWithField(fieldName, user);
private _defaultPasswordAuthenticator(user, password);
private options;
constructor(services: any, options: AccountsServerOptions);
loginWithService(serviceName: string, params: any, infos: ConnectionInformationsType): Promise<LoginReturnType>;
loginWithUser(user: UserObjectType, infos: ConnectionInformationsType): Promise<LoginReturnType>;
resumeSession(accessToken: string): Promise<UserObjectType | null>;
private findSessionByAccessToken(accessToken);
private createTokens(sessionId, isImpersonated?);
private sanitizeUser(user);
}
declare const _default: AccountsServer;
export default _default;

@@ -46,125 +46,41 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var pick = require("lodash/pick");
var omit = require("lodash/omit");
var isString = require("lodash/isString");
var isPlainObject = require("lodash/isPlainObject");
var isFunction = require("lodash/isFunction");
var find = require("lodash/find");
var includes = require("lodash/includes");
var get = require("lodash/get");
var events_1 = require("events");
var lodash_1 = require("lodash");
var jwt = require("jsonwebtoken");
var common_1 = require("@accounts/common");
var config_1 = require("./config");
var encryption_1 = require("./encryption");
var tokens_1 = require("./tokens");
var email_1 = require("./email");
var email_templates_1 = require("./email-templates");
exports.ServerHooks = {
LoginSuccess: 'LoginSuccess',
LoginError: 'LoginError',
LogoutSuccess: 'LogoutSuccess',
LogoutError: 'LogoutError',
CreateUserSuccess: 'CreateUserSuccess',
CreateUserError: 'CreateUserError',
ResumeSessionSuccess: 'ResumeSessionSuccess',
ResumeSessionError: 'ResumeSessionError',
RefreshTokensSuccess: 'RefreshTokensSuccess',
RefreshTokensError: 'RefreshTokensError',
ImpersonationSuccess: 'ImpersonationSuccess',
ImpersonationError: 'ImpersonationError',
var defaultOptions = {
tokenSecret: 'secret',
tokenConfigs: {
accessToken: {
expiresIn: '90m',
},
refreshToken: {
expiresIn: '7d',
},
},
};
var AccountsServer = (function () {
function AccountsServer() {
function AccountsServer(services, options) {
this.services = services;
this.options = __assign({}, defaultOptions, options);
this.db = this.options.db;
for (var service in this.services) {
this.services[service].db = this.db;
}
}
AccountsServer.prototype.config = function (options, db) {
this._options = __assign({}, config_1.default, options);
if (!db) {
throw new common_1.AccountsError('A database driver is required');
}
this.db = db;
this.email = this._options.sendMail
? { sendMail: this._options.sendMail }
: new email_1.default(this._options.email);
this.emailTemplates = email_templates_1.default;
if (!this.hooks) {
this.hooks = new events_1.EventEmitter();
}
};
AccountsServer.prototype.options = function () {
return this._options;
};
AccountsServer.prototype.onLoginSuccess = function (callback) {
return this._on(exports.ServerHooks.LoginSuccess, callback);
};
AccountsServer.prototype.onLoginError = function (callback) {
return this._on(exports.ServerHooks.LoginError, callback);
};
AccountsServer.prototype.onLogoutSuccess = function (callback) {
return this._on(exports.ServerHooks.LogoutSuccess, callback);
};
AccountsServer.prototype.onLogoutError = function (callback) {
return this._on(exports.ServerHooks.LogoutError, callback);
};
AccountsServer.prototype.onCreateUserSuccess = function (callback) {
return this._on(exports.ServerHooks.CreateUserSuccess, callback);
};
AccountsServer.prototype.onCreateUserError = function (callback) {
return this._on(exports.ServerHooks.CreateUserError, callback);
};
AccountsServer.prototype.onResumeSessionSuccess = function (callback) {
return this._on(exports.ServerHooks.ResumeSessionSuccess, callback);
};
AccountsServer.prototype.onResumeSessionError = function (callback) {
return this._on(exports.ServerHooks.ResumeSessionError, callback);
};
AccountsServer.prototype.onRefreshTokensSuccess = function (callback) {
return this._on(exports.ServerHooks.RefreshTokensSuccess, callback);
};
AccountsServer.prototype.onRefreshTokensError = function (callback) {
return this._on(exports.ServerHooks.RefreshTokensError, callback);
};
AccountsServer.prototype.onImpersonationSuccess = function (callback) {
return this._on(exports.ServerHooks.ImpersonationSuccess, callback);
};
AccountsServer.prototype.onImpersonationError = function (callback) {
return this._on(exports.ServerHooks.ImpersonationError, callback);
};
AccountsServer.prototype.loginWithPassword = function (user, password, ip, userAgent) {
AccountsServer.prototype.loginWithService = function (serviceName, params, infos) {
return __awaiter(this, void 0, void 0, function () {
var foundUser, loginResult, error_1;
var user;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 6, , 7]);
if (!user || !password) {
throw new common_1.AccountsError('Unrecognized options for login request', user, 400);
if (!this.services[serviceName]) {
throw new Error("No service with the name " + serviceName + " was registered.");
}
if ((!isString(user) && !isPlainObject(user)) || !isString(password)) {
throw new common_1.AccountsError('Match failed', user, 400);
}
foundUser = void 0;
if (!this._options.passwordAuthenticator) return [3, 2];
return [4, this._externalPasswordAuthenticator(this._options.passwordAuthenticator, user, password)];
return [4, this.services[serviceName].authenticate(params)];
case 1:
foundUser = _a.sent();
return [3, 4];
case 2: return [4, this._defaultPasswordAuthenticator(user, password)];
case 3:
foundUser = _a.sent();
_a.label = 4;
case 4:
if (!foundUser) {
throw new common_1.AccountsError('User not found', user, 403);
user = _a.sent();
if (!user) {
throw new Error("Service " + serviceName + " was not able to authenticate user");
}
return [4, this.loginWithUser(foundUser, ip, userAgent)];
case 5:
loginResult = _a.sent();
this.hooks.emit(exports.ServerHooks.LoginSuccess, loginResult);
return [2, loginResult];
case 6:
error_1 = _a.sent();
this.hooks.emit(exports.ServerHooks.LoginError, error_1);
throw error_1;
case 7: return [2];
return [2, this.loginWithUser(user, infos)];
}

@@ -174,15 +90,10 @@ });

};
AccountsServer.prototype._externalPasswordAuthenticator = function (authFn, user, password) {
AccountsServer.prototype.loginWithUser = function (user, infos) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2, authFn(user, password)];
});
});
};
AccountsServer.prototype.loginWithUser = function (user, ip, userAgent) {
return __awaiter(this, void 0, void 0, function () {
var sessionId, _a, accessToken, refreshToken, loginResult;
var ip, userAgent, sessionId, _a, accessToken, refreshToken, loginResult;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4, this.db.createSession(user.id, ip, userAgent)];
case 0:
ip = infos.ip, userAgent = infos.userAgent;
return [4, this.db.createSession(user.id, ip, userAgent)];
case 1:

@@ -193,3 +104,3 @@ sessionId = _b.sent();

sessionId: sessionId,
user: this._sanitizeUser(user),
user: this.sanitizeUser(user),
tokens: {

@@ -205,93 +116,13 @@ refreshToken: refreshToken,

};
AccountsServer.prototype.createUser = function (user) {
AccountsServer.prototype.resumeSession = function (accessToken) {
return __awaiter(this, void 0, void 0, function () {
var _a, _b, password, validateNewUser, proposedUserObject, userId, error_2;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_c.trys.push([0, 10, , 11]);
if (!common_1.validators.validateUsername(user.username) &&
!common_1.validators.validateEmail(user.email)) {
throw new common_1.AccountsError('Username or Email is required', {
username: user && user.username,
email: user && user.email,
});
}
_a = user.username;
if (!_a) return [3, 2];
return [4, this.db.findUserByUsername(user.username)];
case 1:
_a = (_c.sent());
_c.label = 2;
case 2:
if (_a) {
throw new common_1.AccountsError('Username already exists', {
username: user.username,
});
}
_b = user.email;
if (!_b) return [3, 4];
return [4, this.db.findUserByEmail(user.email)];
case 3:
_b = (_c.sent());
_c.label = 4;
case 4:
if (_b) {
throw new common_1.AccountsError('Email already exists', { email: user.email });
}
password = void 0;
if (!user.password) return [3, 6];
return [4, this._hashAndBcryptPassword(user.password)];
case 5:
password = _c.sent();
_c.label = 6;
case 6:
validateNewUser = this.options().validateNewUser;
proposedUserObject = {
username: user.username,
email: user.email && user.email.toLowerCase(),
password: password,
profile: user.profile,
};
if (!isFunction(validateNewUser)) return [3, 8];
return [4, validateNewUser(proposedUserObject)];
case 7:
_c.sent();
_c.label = 8;
case 8: return [4, this.db.createUser(proposedUserObject)];
case 9:
userId = _c.sent();
this.hooks.emit(exports.ServerHooks.CreateUserSuccess, userId, proposedUserObject);
return [2, userId];
case 10:
error_2 = _c.sent();
this.hooks.emit(exports.ServerHooks.CreateUserError, error_2);
throw error_2;
case 11: return [2];
}
});
});
};
AccountsServer.prototype.impersonate = function (accessToken, username, ip, userAgent) {
return __awaiter(this, void 0, void 0, function () {
var session, user, impersonatedUser, isAuthorized, newSessionId, impersonationTokens, impersonationResult, e_1;
var session, user, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 6, , 7]);
if (!isString(accessToken)) {
throw new common_1.AccountsError('An access token is required');
}
try {
jwt.verify(accessToken, this._options.tokenSecret);
}
catch (err) {
throw new common_1.AccountsError('Access token is not valid');
}
_a.trys.push([0, 4, , 5]);
return [4, this.findSessionByAccessToken(accessToken)];
case 1:
session = _a.sent();
if (!session.valid) {
throw new common_1.AccountsError('Session is not valid for user');
}
if (!session.valid) return [3, 3];
return [4, this.db.findUserById(session.userId)];

@@ -301,35 +132,10 @@ case 2:

if (!user) {
throw new common_1.AccountsError('User not found');
throw new Error('User not found');
}
return [4, this.db.findUserByUsername(username)];
case 3:
impersonatedUser = _a.sent();
if (!impersonatedUser) {
throw new common_1.AccountsError("User " + username + " not found");
}
if (!this._options.impersonationAuthorize) {
return [2, { authorized: false }];
}
return [4, this._options.impersonationAuthorize(user, impersonatedUser)];
return [2, this.sanitizeUser(user)];
case 3: return [2, null];
case 4:
isAuthorized = _a.sent();
if (!isAuthorized) {
return [2, { authorized: false }];
}
return [4, this.db.createSession(impersonatedUser.id, ip, userAgent)];
case 5:
newSessionId = _a.sent();
impersonationTokens = this.createTokens(newSessionId, true);
impersonationResult = {
authorized: true,
tokens: impersonationTokens,
user: this._sanitizeUser(impersonatedUser),
};
this.hooks.emit(exports.ServerHooks.ImpersonationSuccess, user, impersonationResult);
return [2, impersonationResult];
case 6:
e_1 = _a.sent();
this.hooks.emit(exports.ServerHooks.ImpersonationError, e_1);
throw e_1;
case 7: return [2];
case 5: return [2];
}

@@ -339,22 +145,17 @@ });

};
AccountsServer.prototype.refreshTokens = function (accessToken, refreshToken, ip, userAgent) {
AccountsServer.prototype.findSessionByAccessToken = function (accessToken) {
return __awaiter(this, void 0, void 0, function () {
var sessionId, decodedAccessToken, session, user, tokens, result, err_1;
var sessionId, decodedAccessToken, session;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 6, , 7]);
if (!isString(accessToken) || !isString(refreshToken)) {
throw new common_1.AccountsError('An accessToken and refreshToken are required');
if (!lodash_1.isString(accessToken)) {
throw new Error('An accessToken is required');
}
sessionId = void 0;
try {
jwt.verify(refreshToken, this._options.tokenSecret);
decodedAccessToken = jwt.verify(accessToken, this._options.tokenSecret, {
ignoreExpiration: true,
});
decodedAccessToken = jwt.verify(accessToken, this.options.tokenSecret);
sessionId = decodedAccessToken.data.sessionId;
}
catch (err) {
throw new common_1.AccountsError('Tokens are not valid');
throw new Error('Tokens are not valid');
}

@@ -365,31 +166,5 @@ return [4, this.db.findSessionById(sessionId)];

if (!session) {
throw new common_1.AccountsError('Session not found');
throw new Error('Session not found');
}
if (!session.valid) return [3, 4];
return [4, this.db.findUserById(session.userId)];
case 2:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: session.userId });
}
tokens = this.createTokens(sessionId);
return [4, this.db.updateSession(sessionId, ip, userAgent)];
case 3:
_a.sent();
result = {
sessionId: sessionId,
user: this._sanitizeUser(user),
tokens: tokens,
};
this.hooks.emit(exports.ServerHooks.RefreshTokensSuccess, result);
return [2, result];
case 4: throw new common_1.AccountsError('Session is no longer valid', {
id: session.userId,
});
case 5: return [3, 7];
case 6:
err_1 = _a.sent();
this.hooks.emit(exports.ServerHooks.RefreshTokensError, err_1);
throw err_1;
case 7: return [2];
return [2, session];
}

@@ -401,3 +176,3 @@ });

if (isImpersonated === void 0) { isImpersonated = false; }
var _a = this._options, _b = _a.tokenSecret, tokenSecret = _b === void 0 ? config_1.default.tokenSecret : _b, _c = _a.tokenConfigs, tokenConfigs = _c === void 0 ? config_1.default.tokenConfigs : _c;
var _a = this.options, tokenSecret = _a.tokenSecret, tokenConfigs = _a.tokenConfigs;
var accessToken = tokens_1.generateAccessToken({

@@ -409,443 +184,16 @@ data: {

secret: tokenSecret,
config: tokenConfigs.accessToken || {},
config: tokenConfigs.accessToken,
});
var refreshToken = tokens_1.generateRefreshToken({
secret: tokenSecret,
config: tokenConfigs.refreshToken || {},
config: tokenConfigs.refreshToken,
});
return { accessToken: accessToken, refreshToken: refreshToken };
};
AccountsServer.prototype.logout = function (accessToken) {
return __awaiter(this, void 0, void 0, function () {
var session, user, error_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 6, , 7]);
return [4, this.findSessionByAccessToken(accessToken)];
case 1:
session = _a.sent();
if (!session.valid) return [3, 4];
return [4, this.db.findUserById(session.userId)];
case 2:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: session.userId });
}
return [4, this.db.invalidateSession(session.sessionId)];
case 3:
_a.sent();
this.hooks.emit(exports.ServerHooks.LogoutSuccess, this._sanitizeUser(user), session, accessToken);
return [3, 5];
case 4: throw new common_1.AccountsError('Session is no longer valid', {
id: session.userId,
});
case 5: return [3, 7];
case 6:
error_3 = _a.sent();
this.hooks.emit(exports.ServerHooks.LogoutError, error_3);
throw error_3;
case 7: return [2];
}
});
});
AccountsServer.prototype.sanitizeUser = function (user) {
return lodash_1.omit(user, ['services']);
};
AccountsServer.prototype.resumeSession = function (accessToken) {
return __awaiter(this, void 0, void 0, function () {
var session, user, e_2, e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 8, , 9]);
return [4, this.findSessionByAccessToken(accessToken)];
case 1:
session = _a.sent();
if (!session.valid) return [3, 7];
return [4, this.db.findUserById(session.userId)];
case 2:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: session.userId });
}
if (!this._options.resumeSessionValidator) return [3, 6];
_a.label = 3;
case 3:
_a.trys.push([3, 5, , 6]);
return [4, this._options.resumeSessionValidator(user, session)];
case 4:
_a.sent();
return [3, 6];
case 5:
e_2 = _a.sent();
throw new common_1.AccountsError(e_2, { id: session.userId }, 403);
case 6:
this.hooks.emit(exports.ServerHooks.ResumeSessionSuccess, user, accessToken);
return [2, this._sanitizeUser(user)];
case 7:
this.hooks.emit(exports.ServerHooks.ResumeSessionError, new common_1.AccountsError('Invalid Session', { id: session.userId }));
return [2, null];
case 8:
e_3 = _a.sent();
this.hooks.emit(exports.ServerHooks.ResumeSessionError, e_3);
throw e_3;
case 9: return [2];
}
});
});
};
AccountsServer.prototype.findSessionByAccessToken = function (accessToken) {
return __awaiter(this, void 0, void 0, function () {
var sessionId, decodedAccessToken, session;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!isString(accessToken)) {
throw new common_1.AccountsError('An accessToken is required');
}
try {
decodedAccessToken = jwt.verify(accessToken, this._options.tokenSecret);
sessionId = decodedAccessToken.data.sessionId;
}
catch (err) {
throw new common_1.AccountsError('Tokens are not valid');
}
return [4, this.db.findSessionById(sessionId)];
case 1:
session = _a.sent();
if (!session) {
throw new common_1.AccountsError('Session not found');
}
return [2, session];
}
});
});
};
AccountsServer.prototype.findUserByEmail = function (email) {
return this.db.findUserByEmail(email);
};
AccountsServer.prototype.findUserByUsername = function (username) {
return this.db.findUserByUsername(username);
};
AccountsServer.prototype.findUserById = function (userId) {
return this.db.findUserById(userId);
};
AccountsServer.prototype.addEmail = function (userId, newEmail, verified) {
return this.db.addEmail(userId, newEmail, verified);
};
AccountsServer.prototype.removeEmail = function (userId, email) {
return this.db.removeEmail(userId, email);
};
AccountsServer.prototype.verifyEmail = function (token) {
return __awaiter(this, void 0, void 0, function () {
var user, verificationTokens, tokenRecord, emailRecord;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByEmailVerificationToken(token)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('Verify email link expired');
}
verificationTokens = get(user, ['services', 'email', 'verificationTokens'], []);
tokenRecord = find(verificationTokens, function (t) { return t.token === token; });
if (!tokenRecord) {
throw new common_1.AccountsError('Verify email link expired');
}
emailRecord = find(user.emails, function (e) { return e.address === tokenRecord.address; });
if (!emailRecord) {
throw new common_1.AccountsError('Verify email link is for unknown address');
}
return [4, this.db.verifyEmail(user.id, emailRecord.address)];
case 2:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype.resetPassword = function (token, newPassword) {
return __awaiter(this, void 0, void 0, function () {
var user, resetTokens, resetTokenRecord, emails, password;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByResetPasswordToken(token)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('Reset password link expired');
}
resetTokens = get(user, ['services', 'password', 'reset']);
resetTokenRecord = find(resetTokens, function (t) { return t.token === token; });
if (this._isTokenExpired(token, resetTokenRecord)) {
throw new common_1.AccountsError('Reset password link expired');
}
emails = user.emails || [];
if (!includes(emails.map(function (email) { return email.address; }), resetTokenRecord.address)) {
throw new common_1.AccountsError('Token has invalid email address');
}
return [4, this._hashAndBcryptPassword(newPassword)];
case 2:
password = _a.sent();
return [4, this.db.setResetPasssword(user.id, resetTokenRecord.address, password, token)];
case 3:
_a.sent();
this.db.invalidateAllSessions(user.id);
return [2];
}
});
});
};
AccountsServer.prototype.setPassword = function (userId, newPassword) {
return __awaiter(this, void 0, void 0, function () {
var password;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, encryption_1.bcryptPassword(newPassword)];
case 1:
password = _a.sent();
return [2, this.db.setPasssword(userId, password)];
}
});
});
};
AccountsServer.prototype.setProfile = function (userId, profile) {
return __awaiter(this, void 0, void 0, function () {
var user;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserById(userId)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: userId });
}
return [4, this.db.setProfile(userId, profile)];
case 2:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype.updateProfile = function (userId, profile) {
return __awaiter(this, void 0, void 0, function () {
var user;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserById(userId)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: userId });
}
return [2, this.db.setProfile(userId, __assign({}, user.profile, profile))];
}
});
});
};
AccountsServer.prototype.sendVerificationEmail = function (address) {
return __awaiter(this, void 0, void 0, function () {
var user, email, emails, token, resetPasswordMail;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByEmail(address)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { email: address });
}
if (!address) {
email = find(user.emails, function (e) { return !e.verified; });
address = email && email.address;
}
emails = user.emails || [];
if (!address || !includes(emails.map(function (email) { return email.address; }), address)) {
throw new common_1.AccountsError('No such email address for user');
}
token = tokens_1.generateRandomToken();
return [4, this.db.addEmailVerificationToken(user.id, address, token)];
case 2:
_a.sent();
resetPasswordMail = this._prepareMail(address, token, this._sanitizeUser(user), 'verify-email', this.emailTemplates.verifyEmail, this.emailTemplates.from);
return [4, this.email.sendMail(resetPasswordMail)];
case 3:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype.sendResetPasswordEmail = function (address) {
return __awaiter(this, void 0, void 0, function () {
var user, token, resetPasswordMail;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByEmail(address)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { email: address });
}
address = this._getFirstUserEmail(user, address);
token = tokens_1.generateRandomToken();
return [4, this.db.addResetPasswordToken(user.id, address, token)];
case 2:
_a.sent();
resetPasswordMail = this._prepareMail(address, token, this._sanitizeUser(user), 'reset-password', this.emailTemplates.resetPassword, this.emailTemplates.from);
return [4, this.email.sendMail(resetPasswordMail)];
case 3:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype.sendEnrollmentEmail = function (address) {
return __awaiter(this, void 0, void 0, function () {
var user, token, enrollmentMail;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByEmail(address)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { email: address });
}
address = this._getFirstUserEmail(user, address);
token = tokens_1.generateRandomToken();
return [4, this.db.addResetPasswordToken(user.id, address, token, 'enroll')];
case 2:
_a.sent();
enrollmentMail = this._prepareMail(address, token, this._sanitizeUser(user), 'enroll-account', this.emailTemplates.enrollAccount, this.emailTemplates.from);
return [4, this.email.sendMail(enrollmentMail)];
case 3:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype._on = function (eventName, callback) {
var _this = this;
this.hooks.on(eventName, callback);
return function () { return _this.hooks.removeListener(eventName, callback); };
};
AccountsServer.prototype._isTokenExpired = function (token, tokenRecord) {
return (!tokenRecord ||
Number(tokenRecord.when) + this._options.emailTokensExpiry < Date.now());
};
AccountsServer.prototype._internalUserSanitizer = function (user) {
return omit(user, ['services']);
};
AccountsServer.prototype._sanitizeUser = function (user) {
var userObjectSanitizer = this.options().userObjectSanitizer;
return userObjectSanitizer(this._internalUserSanitizer(user), omit, pick);
};
AccountsServer.prototype._prepareMail = function (to, token, user, pathFragment, emailTemplate, from) {
if (this._options.prepareMail) {
return this._options.prepareMail(to, token, user, pathFragment, emailTemplate, from);
}
return this._defaultPrepareEmail(to, token, user, pathFragment, emailTemplate, from);
};
AccountsServer.prototype._defaultPrepareEmail = function (to, token, user, pathFragment, emailTemplate, from) {
var tokenizedUrl = this._defaultCreateTokenizedUrl(pathFragment, token);
return {
from: emailTemplate.from || from,
to: to,
subject: emailTemplate.subject(user),
text: emailTemplate.text(user, tokenizedUrl),
};
};
AccountsServer.prototype._defaultCreateTokenizedUrl = function (pathFragment, token) {
var siteUrl = this._options.siteUrl || config_1.default.siteUrl;
return siteUrl + "/" + pathFragment + "/" + token;
};
AccountsServer.prototype._getFirstUserEmail = function (user, address) {
if (!address && user.emails && user.emails[0]) {
address = user.emails[0].address;
}
var emails = user.emails || [];
if (!address ||
!includes(emails.map(function (email) { return email.address; }), address)) {
throw new common_1.AccountsError('No such email address for user');
}
return address;
};
AccountsServer.prototype._hashAndBcryptPassword = function (password) {
return __awaiter(this, void 0, void 0, function () {
var hashAlgorithm, hashedPassword;
return __generator(this, function (_a) {
hashAlgorithm = this._options.passwordHashAlgorithm;
hashedPassword = hashAlgorithm
? encryption_1.hashPassword(password, hashAlgorithm)
: password;
return [2, encryption_1.bcryptPassword(hashedPassword)];
});
});
};
AccountsServer.prototype._validateLoginWithField = function (fieldName, user) {
var allowedFields = this._options.allowedLoginFields || [];
var isAllowed = allowedFields.includes(fieldName);
if (!isAllowed) {
throw new common_1.AccountsError("Login with " + fieldName + " is not allowed!", user);
}
};
AccountsServer.prototype._defaultPasswordAuthenticator = function (user, password) {
return __awaiter(this, void 0, void 0, function () {
var _a, username, email, id, foundUser, hash, hashAlgorithm, pass, isPasswordValid;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = isString(user)
? common_1.toUsernameAndEmail({ user: user })
: common_1.toUsernameAndEmail(__assign({}, user)), username = _a.username, email = _a.email, id = _a.id;
if (!id) return [3, 2];
this._validateLoginWithField('id', user);
return [4, this.db.findUserById(id)];
case 1:
foundUser = _b.sent();
return [3, 6];
case 2:
if (!username) return [3, 4];
this._validateLoginWithField('username', user);
return [4, this.db.findUserByUsername(username)];
case 3:
foundUser = _b.sent();
return [3, 6];
case 4:
if (!email) return [3, 6];
this._validateLoginWithField('email', user);
return [4, this.db.findUserByEmail(email)];
case 5:
foundUser = _b.sent();
_b.label = 6;
case 6:
if (!foundUser) {
throw new common_1.AccountsError('User not found', user, 403);
}
return [4, this.db.findPasswordHash(foundUser.id)];
case 7:
hash = _b.sent();
if (!hash) {
throw new common_1.AccountsError('User has no password set', user, 403);
}
hashAlgorithm = this._options.passwordHashAlgorithm;
pass = hashAlgorithm
? encryption_1.hashPassword(password, hashAlgorithm)
: password;
return [4, encryption_1.verifyPassword(pass, hash)];
case 8:
isPasswordValid = _b.sent();
if (!isPasswordValid) {
throw new common_1.AccountsError('Incorrect password', user, 403);
}
return [2, foundUser];
}
});
});
};
return AccountsServer;
}());
exports.AccountsServer = AccountsServer;
exports.default = new AccountsServer();
exports.default = AccountsServer;
//# sourceMappingURL=accounts-server.js.map

@@ -1,6 +0,3 @@

import Accounts, { AccountsServer } from './accounts-server';
import * as encryption from './encryption';
import { DBInterface } from './db-interface';
import config from './config';
export default Accounts;
export { AccountsServer, encryption, config, DBInterface };
import AccountsServer from './accounts-server';
export { DBInterface } from './types';
export { AccountsServer };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var accounts_server_1 = require("./accounts-server");
exports.AccountsServer = accounts_server_1.AccountsServer;
var encryption = require("./encryption");
exports.encryption = encryption;
var config_1 = require("./config");
exports.config = config_1.default;
exports.default = accounts_server_1.default;
exports.AccountsServer = accounts_server_1.default;
//# sourceMappingURL=index.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var jwt = require("jsonwebtoken");
var crypto_1 = require("crypto");
var crypto = require("crypto");
exports.generateRandomToken = function (length) {
if (length === void 0) { length = 43; }
return crypto_1.randomBytes(length).toString('hex');
return crypto.randomBytes(length).toString('hex');
};

@@ -9,0 +9,0 @@ exports.generateAccessToken = function (_a) {

{
"name": "@accounts/server",
"version": "0.1.0-alpha.4b98ebbe",
"description": "Fullstack authentication and accounts-management",
"version": "0.1.0-alpha.4d9cf8a2",
"license": "MIT",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"publishConfig": {
"access": "public"
},
"scripts": {
"start": "webpack -p --config --progress --watch",
"clean": "rimraf lib",
"precompile": "npm run clean",
"start": "tsc --watch",
"compile": "tsc",
"prepublish": "npm run compile",
"test": "npm run testonly",
"test-ci": "npm lint && npm coverage",
"testonly": "jest",
"coverage": "npm run testonly -- --coverage",
"coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
"coverage": "jest --coverage"
},
"jest": {
"transform": {
".(ts|tsx)": "<rootDir>/../../node_modules/ts-jest/preprocessor.js"
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$",
"testRegex": "./__tests__/.*.(ts|tsx)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js"

@@ -33,34 +24,8 @@ ],

},
"repository": {
"type": "git",
"url": "https://github.com/js-accounts/accounts/tree/master/packages/server"
},
"keywords": [
"rest",
"graphql",
"grant",
"auth",
"authentication",
"accounts",
"users",
"oauth"
],
"author": "Tim Mikeladze",
"license": "MIT",
"dependencies": {
"@accounts/common": "^0.1.0-alpha.4b98ebbe",
"babel-polyfill": "^6.23.0",
"bcryptjs": "^2.4.0",
"crypto": "^0.0.3",
"emailjs": "^1.0.8",
"jsonwebtoken": "^7.2.1",
"jwt-decode": "^2.1.0",
"lodash": "^4.16.4"
"jsonwebtoken": "^7.4.1"
},
"devDependencies": {
"coveralls": "^2.11.14",
"jest": "^18.0.0",
"localstorage-polyfill": "^1.0.1",
"rimraf": "^2.6.1"
"peerDependencies": {
"@accounts/common": "^0.1.0"
}
}
{
"extends": "../../tsconfig",
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"typeRoots": [
"node_modules/@types"
]
"outDir": "./lib"
},

@@ -10,0 +7,0 @@ "exclude": [

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc