0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-04-15 03:01:37 -05:00

Created Session Model ()

refs 

- Created session model for session table
- Added model relations
- Added unit test coverage
This commit is contained in:
Fabien O'Carroll 2018-09-27 19:31:39 +07:00 committed by Katharina Irrgang
parent 1d17f2aa91
commit 4d9414b5d2
4 changed files with 323 additions and 0 deletions
core
server/models
test/unit/models

View file

@ -26,6 +26,7 @@ models = [
'refreshtoken',
'role',
'settings',
'session',
'subscriber',
'tag',
'user',

View file

@ -0,0 +1,81 @@
const ghostBookshelf = require('./base');
const Session = ghostBookshelf.Model.extend({
tableName: 'sessions',
parse(attrs) {
attrs.session_data = JSON.parse(attrs.session_data);
return attrs;
},
format(attrs) {
// CASE: format will be called when formatting all data for the DB
// including for SELECTs meaning that if we call findOne without
// a session_data property we'll get unintended JSON.stringify(undefined) calls
if (attrs.session_data) {
attrs.session_data = JSON.stringify(attrs.session_data);
}
return attrs;
},
user() {
return this.belongsTo('User');
}
}, {
permittedOptions(methodName) {
const permittedOptions = ghostBookshelf.Model.permittedOptions.call(this, methodName);
if (methodName === 'upsert') {
return permittedOptions.concat('session_id');
}
if (methodName === 'destroy') {
return permittedOptions.concat('session_id');
}
return permittedOptions;
},
destroy(unfilteredOptions) {
if (unfilteredOptions.id) {
return ghostBookshelf.Model.destroy.call(this, unfilteredOptions);
}
const options = this.filterOptions(unfilteredOptions, 'destroy');
// Fetch the object before destroying it, so that the changed data is available to events
return this.forge({session_id: options.session_id})
.fetch(options)
.then((obj) => {
return obj.destroy(options);
});
},
upsert(data, unfilteredOptions) {
const options = this.filterOptions(unfilteredOptions, 'upsert');
const sessionId = options.session_id;
const sessionData = data.session_data;
const userId = sessionData.user_id;
return this.findOne({session_id: sessionId, user_id: userId}, options)
.then((model) => {
if (model) {
return this.edit({
session_data: sessionData
}, Object.assign(options, {
id: model.id
}));
}
return this.add({
session_id: sessionId,
session_data: sessionData,
user_id: userId
}, options);
});
}
});
const Sessions = ghostBookshelf.Collection.extend({
model: Session
});
module.exports = {
Session: ghostBookshelf.model('Session', Session),
Sessions: ghostBookshelf.collection('Sessions', Sessions)
};

View file

@ -249,6 +249,10 @@ User = ghostBookshelf.Model.extend({
return this.hasMany('Posts', 'created_by');
},
sessions: function sessions() {
return this.hasMany('Sessions');
},
roles: function roles() {
return this.belongsToMany('Role');
},

View file

@ -0,0 +1,237 @@
const should = require('should');
const sinon = require('sinon');
const models = require('../../../server/models');
const sandbox = sinon.sandbox.create();
describe('Unit: models/session', function () {
let sandbox;
before(function () {
models.init();
sandbox = sinon.sandbox.create();
});
afterEach(function () {
sandbox.restore();
});
describe('parse', function () {
const parse = function parse(attrs) {
return new models.Session().parse(attrs);
};
it('converts session_data to an object', function () {
const attrs = {
id: 'something',
session_data: JSON.stringify({
some: 'data'
})
};
const parsed = parse(attrs);
should.equal(typeof parsed.session_data, 'object');
should.equal(parsed.session_data.some, 'data');
});
});
describe('format', function () {
const format = function format(attrs) {
return new models.Session().format(attrs);
};
it('converts session_data to a string', function () {
const attrs = {
id: 'something',
session_data: {
some: 'data'
}
};
const formatted = format(attrs);
should.equal(typeof formatted.session_data, 'string');
should.equal(formatted.session_data, JSON.stringify({
some: 'data'
}));
});
it('does not add session_data key if missing', function () {
const attrs = {
id: 'something'
};
const formatted = format(attrs);
should.equal(formatted.session_data, undefined);
});
});
describe('user', function () {
it('sets up the relation to the "User" model', function () {
const model = models.Session.forge({});
const belongsToSpy = sandbox.spy(model, 'belongsTo');
model.user();
should.equal(belongsToSpy.args[0][0], 'User');
});
});
describe('permittedOptions', function () {
let basePermittedOptionsReturnVal;
let basePermittedOptionsStub;
beforeEach(function () {
basePermittedOptionsReturnVal = ['super', 'doopa'];
basePermittedOptionsStub = sandbox.stub(models.Base.Model, 'permittedOptions')
.returns(basePermittedOptionsReturnVal);
});
it('passes the methodName and the context to the base permittedOptions method', function () {
const methodName = 'methodName';
models.Session.permittedOptions(methodName);
should.equal(basePermittedOptionsStub.args[0][0], methodName);
should.equal(basePermittedOptionsStub.thisValues[0], models.Session);
});
it('returns the base permittedOptions result', function () {
const returnedOptions = models.Session.permittedOptions();
should.deepEqual(returnedOptions, basePermittedOptionsReturnVal);
});
it('returns the base permittedOptions result plus "session_id" when methodName is upsert', function () {
const returnedOptions = models.Session.permittedOptions('upsert');
should.deepEqual(returnedOptions, basePermittedOptionsReturnVal.concat('session_id'));
});
it('returns the base permittedOptions result plus "session_id" when methodName is destroy', function () {
const returnedOptions = models.Session.permittedOptions('destroy');
should.deepEqual(returnedOptions, basePermittedOptionsReturnVal.concat('session_id'));
});
});
describe('destroy', function () {
it('calls and returns the Base Model destroy if an id is passed', function () {
const baseDestroyReturnVal = {};
const baseDestroyStub = sandbox.stub(models.Base.Model, 'destroy')
.returns(baseDestroyReturnVal);
const options = {id: 1};
const returnVal = models.Session.destroy(options);
should.equal(baseDestroyStub.args[0][0], options);
should.equal(returnVal, baseDestroyReturnVal);
});
it('calls forge with the session_id, fetchs with the filtered options and then destroys with the options', function (done) {
const model = models.Session.forge({});
const session_id = 23;
const unfilteredOptions = {session_id};
const filteredOptions = {session_id};
const filterOptionsStub = sandbox.stub(models.Session, 'filterOptions')
.returns(filteredOptions);
const forgeStub = sandbox.stub(models.Session, 'forge')
.returns(model);
const fetchStub = sandbox.stub(model, 'fetch')
.resolves(model);
const destroyStub = sandbox.stub(model, 'destroy')
.resolves();
models.Session.destroy(unfilteredOptions).then(() => {
should.equal(filterOptionsStub.args[0][0], unfilteredOptions);
should.equal(filterOptionsStub.args[0][1], 'destroy');
should.deepEqual(forgeStub.args[0][0], {session_id});
should.equal(fetchStub.args[0][0], filteredOptions);
should.equal(destroyStub.args[0][0], filteredOptions);
done();
});
});
});
describe('upsert', function () {
it('calls findOne and then add if findOne results in nothing', function (done) {
const session_id = 314;
const unfilteredOptions = {session_id};
const filteredOptions = {session_id};
const data = {
session_data: {
user_id: 96
}
};
const filterOptionsStub = sandbox.stub(models.Session, 'filterOptions')
.returns(filteredOptions);
const findOneStub = sandbox.stub(models.Session, 'findOne')
.resolves();
const addStub = sandbox.stub(models.Session, 'add');
models.Session.upsert(data, unfilteredOptions).then(() => {
should.equal(filterOptionsStub.args[0][0], unfilteredOptions);
should.equal(filterOptionsStub.args[0][1], 'upsert');
should.deepEqual(findOneStub.args[0][0], {
session_id,
user_id: data.session_data.user_id
});
should.equal(findOneStub.args[0][1], filteredOptions);
should.deepEqual(addStub.args[0][0], {
session_id: filteredOptions.session_id,
session_data: data.session_data,
user_id: data.session_data.user_id
});
should.equal(addStub.args[0][1], filteredOptions);
done();
});
});
it('calls findOne and then edit if findOne results in nothing', function (done) {
const model = models.Session.forge({id: 2});
const session_id = 314;
const unfilteredOptions = {session_id};
const filteredOptions = {session_id};
const data = {
session_data: {
user_id: 96
}
};
const filterOptionsStub = sandbox.stub(models.Session, 'filterOptions')
.returns(filteredOptions);
const findOneStub = sandbox.stub(models.Session, 'findOne')
.resolves(model);
const editStub = sandbox.stub(models.Session, 'edit');
models.Session.upsert(data, unfilteredOptions).then(() => {
should.equal(filterOptionsStub.args[0][0], unfilteredOptions);
should.equal(filterOptionsStub.args[0][1], 'upsert');
should.deepEqual(findOneStub.args[0][0], {
session_id,
user_id: data.session_data.user_id
});
should.equal(findOneStub.args[0][1], filteredOptions);
should.deepEqual(editStub.args[0][0], {
session_data: data.session_data,
});
should.deepEqual(editStub.args[0][1], {
session_id,
id: model.id
});
should.equal(editStub.args[0][1], filteredOptions);
done();
});
});
});
});