/**
* EntryStore is the main class that is used to connect to a running server-side
* EntryStore repository.
* @exports store/Auth
*/
export default class Auth {
/**
* @param {EntryStore} entrystore - a repository instance.
*/
constructor(entrystore) {
this._entryStore = entrystore;
this._listenerCounter = 0;
/**
* @type {Map<string, Function>}
* @private
*/
this._listeners = new Map();
}
/**
*
* @param {String} topic
* @param obj
*/
messageListeners(topic, obj) {
this._listeners.forEach(func => func(topic, obj));
}
/**
* Adds an authentication listener, it will be notified of login and logout events.
* @param {Function} listener
*/
addAuthListener(listener) {
if (listener.__alid == null) {
listener.__alid = `idx_${this._listenerCounter}`;
this._listenerCounter += 1;
}
this._listeners.set(listener.__alid, listener);
}
/**
* Removes an authentication listener
* @param {Function} listener
*/
removeAuthListener(listener) {
if (listener.__alid != null) {
this._listeners.delete(listener.__alid);
}
}
/**
* Yields information about who currently is authenticated against the EntryStore repository.
* @returns {Promise.<EntryInfo>} - upon success an object containing attributes "user" being
* the username, "id" of the user entry,
* and "homecontext" being the entry-id of the home context is provided.
* @see {@link EntryStore#auth auth}
* @see {@link EntryStore#logout logout}
*/
async getUserInfo(forceLookup = false) {
if (this.userInfo && !forceLookup) {
return Promise.resolve(this.userInfo);
}
this.userInfo = await this._entryStore.handleAsync(
this._entryStore.getREST().get(`${this._entryStore._baseURI}auth/user`, null, true), 'getUserInfo');
return this.userInfo;
}
/**
* @returns {Promise.<Entry>} on success the entry for the currently signed in user is provided.
*/
async getUserEntry(forceLookup = false) {
if (this.userEntry && !forceLookup) {
return Promise.resolve(this.userEntry);
}
const userInfo = await this.getUserInfo(forceLookup);
this.userEntry = await this._entryStore.getEntry(this._entryStore.getEntryURI('_principals', userInfo.id), {
asyncContext: 'getUserEntry',
});
return this.userEntry;
}
/**
* Authenticate using credentials containing a user, a password and an optional maxAge
* given in seconds.
*
* @param user
* @param password
* @param maxAge
* @returns {Promise}
*/
async login(user, password, maxAge) {
if (this.userInfo && this.userInfo.user === user) {
return this.getUserInfo();
}
const credentials = {
base: this._entryStore.getBaseURI(),
user,
password,
maxAge,
};
const auth = await this._entryStore.handleAsync(this._entryStore.getREST().auth(credentials), 'login');
if (typeof auth === 'object' && auth.user) {
return auth;
}
this.userInfo = await this._entryStore.getREST().get(`${this._entryStore._baseURI}auth/user`, null, true);
delete this.userEntry;
this._entryStore.getCache().allNeedRefresh();
this.messageListeners('login', this.userInfo);
return this.userInfo;
}
/**
* Logout the currently authorized user.
* @returns {Promise.<{user, id}>} The guest user info
*/
async logout() {
if (this.userInfo && this.userInfo.user === 'guest') {
return this.getUserInfo();
}
// handleAsync returns the original promise passed
await this._entryStore.handleAsync(this._entryStore.getREST().auth({
base: this._entryStore.getBaseURI(),
logout: true,
}), 'logout');
delete this.userEntry;
this._entryStore.getCache().allNeedRefresh();
this.userInfo = { user: 'guest', id: '_guest' };
this.messageListeners('logout', this.userInfo);
return this.userInfo;
}
}