mirror of https://gitee.com/bigwinds/arangodb
163 lines
4.0 KiB
JavaScript
163 lines
4.0 KiB
JavaScript
'use strict';
|
|
const _ = require('lodash');
|
|
const joi = require('joi');
|
|
const internal = require('internal');
|
|
const arangodb = require('@arangodb');
|
|
const db = arangodb.db;
|
|
const Foxx = require('@arangodb/foxx');
|
|
const errors = require('./errors');
|
|
|
|
function getCollection() {
|
|
return db._collection('_sessions');
|
|
}
|
|
|
|
const Session = Foxx.Model.extend({
|
|
schema: {
|
|
_key: joi.string().required(),
|
|
uid: joi.string().allow(null).default(null),
|
|
userData: joi.object().default(Object, 'Empty object'),
|
|
sessionData: joi.object().default(Object, 'Empty object'),
|
|
created: joi.number().integer().default(Date.now, 'Current date'),
|
|
lastAccess: joi.number().integer().default(Date.now, 'Current date'),
|
|
lastUpdate: joi.number().integer().default(Date.now, 'Current date')
|
|
}
|
|
});
|
|
|
|
function generateSessionId() {
|
|
return internal.genRandomAlphaNumbers(20);
|
|
}
|
|
|
|
function createSession(sessionData, userData) {
|
|
const sid = generateSessionId();
|
|
const session = new Session({
|
|
_key: sid,
|
|
uid: (userData && userData._id) || null,
|
|
sessionData: sessionData || {},
|
|
userData: userData || {},
|
|
lastAccess: Date.now()
|
|
});
|
|
const meta = getCollection().save(session.attributes);
|
|
session.set(meta);
|
|
return session;
|
|
}
|
|
|
|
function deleteSession(sid) {
|
|
try {
|
|
getCollection().remove(sid);
|
|
} catch (e) {
|
|
if (
|
|
e instanceof arangodb.ArangoError
|
|
&& e.errorNum === arangodb.ERROR_ARANGO_DOCUMENT_NOT_FOUND
|
|
) {
|
|
throw new errors.SessionNotFound(sid);
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Session.fromClient = function (sid) {
|
|
const collection = getCollection();
|
|
let session;
|
|
db._executeTransaction({
|
|
collections: {
|
|
read: [collection.name()],
|
|
write: [collection.name()]
|
|
},
|
|
action() {
|
|
try {
|
|
session = new Session(collection.document(sid));
|
|
|
|
const internalAccessTime = internal.accessSid(sid);
|
|
if (internalAccessTime) {
|
|
session.set('lastAccess', internalAccessTime);
|
|
}
|
|
session.enforceTimeout();
|
|
|
|
const now = Date.now();
|
|
session.set('lastAccess', now);
|
|
const meta = collection.update(
|
|
session.get('_key'),
|
|
{lastAccess: now}
|
|
);
|
|
session.set(meta);
|
|
} catch (e) {
|
|
if (
|
|
e instanceof arangodb.ArangoError
|
|
&& e.errorNum === arangodb.ERROR_ARANGO_DOCUMENT_NOT_FOUND
|
|
) {
|
|
throw new errors.SessionNotFound(sid);
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return session;
|
|
};
|
|
|
|
_.extend(Session.prototype, {
|
|
forClient() {
|
|
return this.get('_key');
|
|
},
|
|
enforceTimeout() {
|
|
if (this.hasExpired()) {
|
|
throw new errors.SessionExpired(this.get('_key'));
|
|
}
|
|
},
|
|
hasExpired() {
|
|
return this.getTTL() === 0;
|
|
},
|
|
getTTL() {
|
|
return Math.max(0, this.getExpiry() - Date.now());
|
|
},
|
|
getExpiry() {
|
|
const timeout = Number(internal.options()['server.session-timeout']) * 1000;
|
|
return this.get('lastAccess') + timeout;
|
|
},
|
|
setUser(user) {
|
|
if (user) {
|
|
this.set('uid', user.get('_id'));
|
|
this.set('userData', user.get('userData'));
|
|
internal.createSid(this.get('_key'), user.get('user'));
|
|
} else {
|
|
delete this.attributes.uid;
|
|
this.set('userData', {});
|
|
internal.clearSid(this.get('_key'));
|
|
}
|
|
return this;
|
|
},
|
|
save() {
|
|
const now = Date.now();
|
|
const key = this.get('_key');
|
|
this.set('lastAccess', now);
|
|
this.set('lastUpdate', now);
|
|
internal.accessSid(key);
|
|
const meta = getCollection().replace(this.attributes, this.attributes);
|
|
this.set(meta);
|
|
return this;
|
|
},
|
|
delete() {
|
|
const now = Date.now();
|
|
const key = this.get('_key');
|
|
this.set('lastAccess', now);
|
|
this.set('lastUpdate', now);
|
|
try {
|
|
internal.clearSid(key);
|
|
deleteSession(key);
|
|
} catch (e) {
|
|
if (!(e instanceof errors.SessionNotFound)) {
|
|
throw e;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
});
|
|
|
|
exports.create = createSession;
|
|
exports.get = Session.fromClient;
|
|
exports.delete = deleteSession;
|
|
exports.errors = errors;
|