added inactive and reactivate project logic

This commit is contained in:
Henry Oswald 2015-08-13 22:40:28 +01:00
parent 04d3e527d6
commit a0142d4415
10 changed files with 303 additions and 2 deletions

View file

@ -67,3 +67,31 @@ module.exports = DocstoreManager =
error = new Error("docstore api responded with non-success code: #{res.statusCode}")
logger.error err: error, project_id: project_id, doc_id: doc_id, "error updating doc in docstore"
callback(error)
archiveProject: (project_id, callback)->
url = "#{settings.apis.docstore.url}/project/#{project_id}/archive"
logger.log project_id:project_id, "archiving project in docstore"
request.post url, (err, res, docs) ->
if err?
logger.err err:err, project_id:project_id, "error archving project in docstore"
return callback(err)
if 200 <= res.statusCode < 300
callback()
else
error = new Error("docstore api responded with non-success code: #{res.statusCode}")
logger.err err: error, project_id: project_id, "error archiving project in docstore"
return callback(error)
unarchiveProject: (project_id, callback)->
url = "#{settings.apis.docstore.url}/project/#{project_id}/unarchive"
logger.log project_id:project_id, "unarchiving project in docstore"
request.post url, (err, res, docs) ->
if err?
logger.err err:err, project_id:project_id, "error unarchiving project in docstore"
return callback(err)
if 200 <= res.statusCode < 300
callback()
else
error = new Error("docstore api responded with non-success code: #{res.statusCode}")
logger.err err: error, project_id: project_id, "error unarchiving project in docstore"
return callback(error)

View file

@ -0,0 +1,11 @@
InactiveProjectManager = require("./InactiveProjectManager")
module.exports =
deactivateOldProjects: (req, res)->
InactiveProjectManager.deactivateOldProjects 10, (err)->
if err?
res.sendStatus(500)
else
res.sendStatus(200)

View file

@ -0,0 +1,53 @@
async = require("async")
_ = require("lodash")
logger = require("logger-sharelatex")
DocstoreManager = require("../Docstore/DocstoreManager")
ProjectGetter = require("../Project/ProjectGetter")
ProjectUpdateHandler = require("../Project/ProjectUpdateHandler")
Project = require("../../models/Project").Project
MILISECONDS_IN_DAY = 86400000
module.exports = InactiveProjectManager =
reactivateProjectIfRequired: (project_id, callback)->
ProjectGetter.getProject project_id, {inactive:true}, (err, project)->
if err?
logger.err err:err, project_id:project_id, "error getting project"
return callback(err)
logger.log project_id:project_id, inactive:project.inactive, "seeing if need to reactivate project"
if !project.inactive
return callback()
DocstoreManager.unarchiveProject project_id, (err)->
if err?
logger.err err:err, project_id:project_id, "error reactivating project in docstore"
return callback(err)
ProjectUpdateHandler.markAsActive project_id, callback
deactivateOldProjects: (limit, callback)->
sixMonthsAgo = new Date() - (MILISECONDS_IN_DAY * 1)
Project.find()
.where("lastOpened").lt(sixMonthsAgo)
.where("inactive").ne(true)
.select("_id")
.limit(limit)
.exec (err, projects)->
if err?
logger.err err:err, "could not get projects for deactivating"
jobs = _.map projects, (project)->
return (cb)->
InactiveProjectManager.deactivateProject project._id, cb
logger.log numberOfProjects:projects?.length, "deactivating projects"
async.series jobs, callback
deactivateProject: (project_id, callback)->
logger.log project_id:project_id, "deactivating inactive project"
DocstoreManager.archiveProject project_id, (err)->
if err?
logger.err err:err, project_id:project_id, "error deactivating project in docstore"
return callback(err)
ProjectUpdateHandler.markAsInactive project_id, callback

View file

@ -14,6 +14,8 @@ _ = require("underscore")
Settings = require("settings-sharelatex")
SecurityManager = require("../../managers/SecurityManager")
fs = require "fs"
InactiveProjectManager = require("../InactiveData/InactiveProjectManager")
ProjectUpdateHandler = require("./ProjectUpdateHandler")
module.exports = ProjectController =
@ -189,6 +191,10 @@ module.exports = ProjectController =
if user_id == 'openUser'
return cb()
SubscriptionLocator.getUsersSubscription user_id, cb
activate: (cb)->
InactiveProjectManager.reactivateProjectIfRequired project_id, cb
markOpened: (cb)->
ProjectUpdateHandler.markOpened project_id, cb
}, (err, results)->
if err?
logger.err err:err, "error getting details for project page"

View file

@ -1,5 +1,6 @@
Project = require('../../models/Project').Project
logger = require('logger-sharelatex')
Project = require("../../models/Project").Project
module.exports =
markAsUpdated : (project_id, callback)->
@ -8,3 +9,24 @@ module.exports =
Project.update conditions, update, {}, (err)->
if callback?
callback()
markAsOpened : (project_id, callback)->
conditions = {_id:project_id}
update = {lastOpened:Date.now()}
Project.update conditions, update, {}, (err)->
if callback?
callback()
markAsInactive: (project_id, callback)->
conditions = {_id:project_id}
update = {inactive:true}
Project.update conditions, update, {}, (err)->
if callback?
callback()
markAsActive: (project_id, callback)->
conditions = {_id:project_id}
update = { $unset: { inactive: true }}
Project.update conditions, update, {}, (err)->
if callback?
callback()

View file

@ -17,6 +17,8 @@ DeletedDocSchema = new Schema
ProjectSchema = new Schema
name : {type:String, default:'new project'}
lastUpdated : {type:Date, default: () -> new Date()}
lastOpened : {type:Date}
inactive : { type: Boolean }
owner_ref : {type:ObjectId, ref:'User'}
collaberator_refs : [ type:ObjectId, ref:'User' ]
readOnly_refs : [ type:ObjectId, ref:'User' ]

View file

@ -13,7 +13,7 @@ describe "DocstoreManager", ->
apis:
docstore:
url: "docstore.sharelatex.com"
"logger-sharelatex": @logger = {log: sinon.stub(), error: sinon.stub()}
"logger-sharelatex": @logger = {log: sinon.stub(), error: sinon.stub(), err:->}
@requestDefaults.calledWith(jar: false).should.equal true
@ -179,3 +179,42 @@ describe "DocstoreManager", ->
project_id: @project_id
}, "error getting all docs from docstore")
.should.equal true
describe "archiveProject", ->
describe "with a successful response code", ->
beforeEach ->
@request.post = sinon.stub().callsArgWith(1, null, statusCode: 204)
@DocstoreManager.archiveProject @project_id, @callback
it "should call the callback", ->
@callback.called.should.equal true
describe "with a failed response code", ->
beforeEach ->
@request.post = sinon.stub().callsArgWith(1, null, statusCode: 500)
@DocstoreManager.archiveProject @project_id, @callback
it "should call the callback with an error", ->
@callback.calledWith(new Error("docstore api responded with non-success code: 500")).should.equal true
describe "unarchiveProject", ->
describe "with a successful response code", ->
beforeEach ->
@request.post = sinon.stub().callsArgWith(1, null, statusCode: 204)
@DocstoreManager.unarchiveProject @project_id, @callback
it "should call the callback", ->
@callback.called.should.equal true
describe "with a failed response code", ->
beforeEach ->
@request.post = sinon.stub().callsArgWith(1, null, statusCode: 500)
@DocstoreManager.unarchiveProject @project_id, @callback
it "should call the callback with an error", ->
@callback.calledWith(new Error("docstore api responded with non-success code: 500")).should.equal true

View file

@ -0,0 +1,85 @@
should = require('chai').should()
SandboxedModule = require('sandboxed-module')
assert = require('assert')
path = require('path')
sinon = require('sinon')
modulePath = path.join __dirname, "../../../../app/js/Features/InactiveData/InactiveProjectManager"
expect = require("chai").expect
describe "InactiveProjectManager", ->
beforeEach ->
@settings = {}
@DocstoreManager =
unarchiveProject:sinon.stub()
@ProjectUpdateHandler =
markAsActive:sinon.stub()
markAsInactive:sinon.stub()
@ProjectGetter =
getProject:sinon.stub()
@InactiveProjectManager = SandboxedModule.require modulePath, requires:
"settings-sharelatex":@settings
"logger-sharelatex":
log:->
err:->
"../Docstore/DocstoreManager":@DocstoreManager
"../Project/ProjectUpdateHandler":@ProjectUpdateHandler
"../Project/ProjectGetter":@ProjectGetter
@project_id = "1234"
describe "reactivateProjectIfRequired", ->
beforeEach ->
@project = {inactive:true}
@ProjectGetter.getProject.callsArgWith(2, null, @project)
@ProjectUpdateHandler.markAsActive.callsArgWith(1)
it "should call unarchiveProject", (done)->
@DocstoreManager.unarchiveProject.callsArgWith(1)
@InactiveProjectManager.reactivateProjectIfRequired @project_id, (err)=>
@DocstoreManager.unarchiveProject.calledWith(@project_id).should.equal true
@ProjectUpdateHandler.markAsActive.calledWith(@project_id).should.equal true
done()
it "should not mark project as active if error with unarchinging", (done)->
@DocstoreManager.unarchiveProject.callsArgWith(1, "error")
@InactiveProjectManager.reactivateProjectIfRequired @project_id, (err)=>
err.should.equal "error"
@DocstoreManager.unarchiveProject.calledWith(@project_id).should.equal true
@ProjectUpdateHandler.markAsActive.calledWith(@project_id).should.equal false
done()
it "should not call unarchiveProject if it is not inactive", (done)->
delete @project.inactive
@DocstoreManager.unarchiveProject.callsArgWith(1)
@InactiveProjectManager.reactivateProjectIfRequired @project_id, (err)=>
@DocstoreManager.unarchiveProject.calledWith(@project_id).should.equal false
@ProjectUpdateHandler.markAsActive.calledWith(@project_id).should.equal false
done()
describe "deactivateProject", ->
beforeEach ->
it "should call unarchiveProject and markAsInactive", (done)->
@DocstoreManager.unarchiveProject.callsArgWith(1)
@ProjectUpdateHandler.markAsInactive.callsArgWith(1)
@InactiveProjectManager.deactivateProject @project_id, (err)->
@DocstoreManager.unarchiveProject.calledWith(@project_id).should.equal true
@ProjectUpdateHandler.markAsInactive.callsArgWith(@project_id).should.equal true
done()
it "should not call markAsInactive if there was a problem unarchiving", (done)->
@DocstoreManager.unarchiveProject.callsArgWith(1, "errorrr")
@ProjectUpdateHandler.markAsInactive.callsArgWith(1)
@InactiveProjectManager.deactivateProject @project_id, (err)->
err.should.equal "errorrr"
@DocstoreManager.unarchiveProject.calledWith(@project_id).should.equal true
@ProjectUpdateHandler.markAsInactive.callsArgWith(@project_id).should.equal false
done()

View file

@ -42,6 +42,10 @@ describe "ProjectController", ->
userCanAccessProject:sinon.stub()
@EditorController =
renameProject:sinon.stub()
@InactiveProjectManager =
reactivateProjectIfRequired:sinon.stub()
@ProjectUpdateHandler =
markOpened: sinon.stub()
@ProjectController = SandboxedModule.require modulePath, requires:
"settings-sharelatex":@settings
"logger-sharelatex":
@ -57,6 +61,8 @@ describe "ProjectController", ->
'../../models/Project': Project:@ProjectModel
"../../models/User":User:@UserModel
"../../managers/SecurityManager":@SecurityManager
"../InactiveData/InactiveProjectManager":@InactiveProjectManager
"./ProjectUpdateHandler":@ProjectUpdateHandler
@user =
_id:"!£123213kjljkl"
@ -282,6 +288,9 @@ describe "ProjectController", ->
@SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, {})
@SecurityManager.userCanAccessProject.callsArgWith 2, true, "owner"
@ProjectDeleter.unmarkAsDeletedByExternalSource = sinon.stub()
@InactiveProjectManager.reactivateProjectIfRequired.callsArgWith(1)
@ProjectUpdateHandler.markOpened.callsArgWith(1)
it "should render the project/editor page", (done)->
@res.render = (pageName, opts)=>
@ -321,3 +330,16 @@ describe "ProjectController", ->
resCode.should.equal 401
done()
@ProjectController.loadEditor @req, @res
it "should reactivateProjectIfRequired", (done)->
@res.render = (pageName, opts)=>
@InactiveProjectManager.reactivateProjectIfRequired.calledWith(@project_id).should.equal true
done()
@ProjectController.loadEditor @req, @res
it "should mark project as opened", (done)->
@res.render = (pageName, opts)=>
@ProjectUpdateHandler.markOpened.calledWith(@project_id).should.equal true
done()
@ProjectController.loadEditor @req, @res

View file

@ -3,7 +3,7 @@ chai = require('chai').should()
modulePath = "../../../../app/js/Features/Project/ProjectUpdateHandler.js"
SandboxedModule = require('sandboxed-module')
describe 'updating a project', ->
describe 'ProjectUpdateHandler', ->
beforeEach ->
@ -22,3 +22,36 @@ describe 'updating a project', ->
now = Date.now()+""
date.substring(0,5).should.equal now.substring(0,5)
done()
describe "markAsOpened", ->
it 'should send an update to mongo', (done)->
project_id = "project_id"
@handler.markAsOpened project_id, (err)=>
args = @ProjectModel.update.args[0]
args[0]._id.should.equal project_id
date = args[1].lastOpened+""
now = Date.now()+""
date.substring(0,5).should.equal now.substring(0,5)
done()
describe "markAsInactive", ->
it 'should send an update to mongo', (done)->
project_id = "project_id"
@handler.markAsInactive project_id, (err)=>
args = @ProjectModel.update.args[0]
args[0]._id.should.equal project_id
args[1].inactive.should.equal true
done()
describe "markAsActive", ->
it 'should send an update to mongo', (done)->
project_id = "project_id"
@handler.markAsActive project_id, (err)=>
args = @ProjectModel.update.args[0]
args[0]._id.should.equal project_id
args[1]["$unset"].inactive.should.equal true
done()