diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index ff20664c43..174413b248 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -24,6 +24,7 @@ AnalyticsManager = require "../Analytics/AnalyticsManager" Sources = require "../Authorization/Sources" TokenAccessHandler = require '../TokenAccess/TokenAccessHandler' CollaboratorsHandler = require '../Collaborators/CollaboratorsHandler' +Modules = require '../../infrastructure/Modules' crypto = require 'crypto' module.exports = ProjectController = @@ -148,6 +149,11 @@ module.exports = ProjectController = NotificationsHandler.getUserNotifications user_id, cb projects: (cb)-> ProjectGetter.findAllUsersProjects user_id, 'name lastUpdated publicAccesLevel archived owner_ref tokens', cb + v1Projects: (cb) -> + Modules.hooks.fire "findAllV1Projects", user_id, (error, projects = []) -> + if error? and error.message == 'No V1 connection' + return cb(null, projects: [], tags: [], noConnection: true) + return cb(error, projects[0]) # hooks.fire returns an array of results, only need first hasSubscription: (cb)-> LimitationsManager.userHasSubscriptionOrIsGroupMember currentUser, cb user: (cb) -> @@ -157,11 +163,12 @@ module.exports = ProjectController = logger.err err:err, "error getting data for project list page" return next(err) logger.log results:results, user_id:user_id, "rendering project list" - tags = results.tags[0] + v1Tags = results.v1Projects?.tags or [] + tags = results.tags[0].concat(v1Tags) notifications = require("underscore").map results.notifications, (notification)-> notification.html = req.i18n.translate(notification.templateKey, notification.messageOpts) return notification - projects = ProjectController._buildProjectList results.projects + projects = ProjectController._buildProjectList results.projects, results.v1Projects?.projects user = results.user ProjectController._injectProjectOwners projects, (error, projects) -> return next(error) if error? @@ -173,6 +180,8 @@ module.exports = ProjectController = notifications: notifications or [] user: user hasSubscription: results.hasSubscription[0] + isShowingV1Projects: results.v1Projects? + noV1Connection: results.v1Projects?.noConnection } if Settings?.algolia?.app_id? and Settings?.algolia?.read_only_api_key? @@ -280,7 +289,7 @@ module.exports = ProjectController = # Extract data from user's ObjectId timestamp = parseInt(user_id.toString().substring(0, 8), 16) - rolloutPercentage = 5 # Percentage of users to roll out to + rolloutPercentage = 10 # Percentage of users to roll out to if !ProjectController._isInPercentageRollout('autocompile', user_id, rolloutPercentage) # Don't show if user is not part of roll out return cb(null, { enabled: false, showOnboarding: false }) @@ -333,7 +342,7 @@ module.exports = ProjectController = enableTokenAccessUI = ProjectController._isInPercentageRollout( 'linksharing', project.owner_ref, - 40 + 100 ) showLinkSharingOnboarding = enableTokenAccessUI && results.couldShowLinkSharingOnboarding AuthorizationManager.getPrivilegeLevelForProject user_id, project_id, token, (error, privilegeLevel)-> @@ -390,7 +399,7 @@ module.exports = ProjectController = showLinkSharingOnboarding: showLinkSharingOnboarding timer.done() - _buildProjectList: (allProjects)-> + _buildProjectList: (allProjects, v1Projects = [])-> {owned, readAndWrite, readOnly, tokenReadAndWrite, tokenReadOnly} = allProjects projects = [] for project in owned @@ -400,6 +409,8 @@ module.exports = ProjectController = projects.push ProjectController._buildProjectViewModel(project, "readWrite", Sources.INVITE) for project in readOnly projects.push ProjectController._buildProjectViewModel(project, "readOnly", Sources.INVITE) + for project in v1Projects + projects.push ProjectController._buildV1ProjectViewModel(project) # Token-access # Only add these projects if they're not already present, this gives us cascading access # from 'owner' => 'token-read-only' @@ -424,9 +435,20 @@ module.exports = ProjectController = archived: !!project.archived owner_ref: project.owner_ref tokens: project.tokens + isV1Project: false } return model + _buildV1ProjectViewModel: (project) -> + { + id: project.id + name: project.title + lastUpdated: new Date(project.updated_at * 1000) # Convert from epoch + accessLevel: "readOnly", + archived: project.removed || project.archived + isV1Project: true + } + _injectProjectOwners: (projects, callback = (error, projects) ->) -> users = {} for project in projects diff --git a/services/web/app/coffee/Features/User/UserController.coffee b/services/web/app/coffee/Features/User/UserController.coffee index d64883b23b..7dc82c1a7b 100644 --- a/services/web/app/coffee/Features/User/UserController.coffee +++ b/services/web/app/coffee/Features/User/UserController.coffee @@ -51,7 +51,6 @@ module.exports = UserController = updateUserSettings : (req, res)-> user_id = AuthenticationController.getLoggedInUserId(req) - usingExternalAuth = settings.ldap? or settings.saml? logger.log user_id: user_id, "updating account settings" User.findById user_id, (err, user)-> if err? or !user? @@ -84,7 +83,7 @@ module.exports = UserController = user.ace.syntaxValidation = req.body.syntaxValidation user.save (err)-> newEmail = req.body.email?.trim().toLowerCase() - if !newEmail? or newEmail == user.email or usingExternalAuth + if !newEmail? or newEmail == user.email or req.externalAuthenticationSystemUsed() # end here, don't update email AuthenticationController.setInSessionUser(req, {first_name: user.first_name, last_name: user.last_name}) return res.sendStatus 200 diff --git a/services/web/app/views/project/list/item.pug b/services/web/app/views/project/list/item.pug new file mode 100644 index 0000000000..f246ad34d4 --- /dev/null +++ b/services/web/app/views/project/list/item.pug @@ -0,0 +1,40 @@ +.col-xs-6 + input.select-item( + select-individual, + type="checkbox", + ng-model="project.selected" + stop-propagation="click" + aria-label=translate('select_project') + " '{{ project.name }}'" + ) + span + a.projectName( + ng-href="{{projectLink(project)}}" + stop-propagation="click" + ) {{project.name}} + span( + ng-controller="TagListController" + ) + .tag-label( + ng-repeat='tag in project.tags' + stop-propagation="click" + ) + a.label.label-default.tag-label-name( + href, + ng-click="selectTag(tag)" + ) {{tag.name}} + a.label.label-default.tag-label-remove( + href + ng-click="removeProjectFromTag(project, tag)" + ) × + +.col-xs-2 + span.owner {{ownerName()}} + span(ng-if="isLinkSharingProject(project)") + |   + i.fa.fa-link.small( + tooltip=translate("link_sharing") + tooltip-placement="right" + tooltip-append-to-body="true" + ) +.col-xs-4 + span.last-modified {{project.lastUpdated | formatDate}} \ No newline at end of file diff --git a/services/web/app/views/project/list/project-list.pug b/services/web/app/views/project/list/project-list.pug index aba8ed08be..0db4f49400 100644 --- a/services/web/app/views/project/list/project-list.pug +++ b/services/web/app/views/project/list/project-list.pug @@ -114,6 +114,10 @@ ) #{translate("delete_forever")} .row.row-spaced + if noV1Connection + .col-xs-12 + .alert.alert-warning No V1 Connection + .col-xs-12 .card.card-thin.project-list-card ul.list-unstyled.project-list.structured-list( @@ -142,47 +146,15 @@ ng-repeat="project in visibleProjects | orderBy:predicate:reverse", ng-controller="ProjectListItemController" ) - .row(select-row) - .col-xs-6 - input.select-item( - select-individual, - type="checkbox", - ng-model="project.selected" - stop-propagation="click" - aria-label=translate('select_project') + " '{{ project.name }}'" - ) - span - a.projectName( - ng-href="{{projectLink(project)}}" - stop-propagation="click" - ) {{project.name}} - span( - ng-controller="TagListController" - ) - .tag-label( - ng-repeat='tag in project.tags' - stop-propagation="click" - ) - a.label.label-default.tag-label-name( - href, - ng-click="selectTag(tag)" - ) {{tag.name}} - a.label.label-default.tag-label-remove( - href - ng-click="removeProjectFromTag(project, tag)" - ) × - - .col-xs-2 - span.owner {{ownerName()}} - span(ng-if="isLinkSharingProject(project)") - |   - i.fa.fa-link.small( - tooltip=translate("link_sharing") - tooltip-placement="right" - tooltip-append-to-body="true" - ) - .col-xs-4 - span.last-modified {{project.lastUpdated | formatDate}} + .row( + ng-if="!project.isV1Project" + select-row + ) + include ./item + .row( + ng-if="project.isV1Project" + ) + include ./v1-item li( ng-if="visibleProjects.length == 0", ng-cloak diff --git a/services/web/app/views/project/list/side-bar.pug b/services/web/app/views/project/list/side-bar.pug index fe053f0019..9fceb4cc86 100644 --- a/services/web/app/views/project/list/side-bar.pug +++ b/services/web/app/views/project/list/side-bar.pug @@ -45,6 +45,9 @@ a(href) #{translate("shared_with_you")} li(ng-class="{active: (filter == 'archived')}", ng-click="filterProjects('archived')") a(href) #{translate("deleted_projects")} + if isShowingV1Projects + li(ng-class="{active: (filter == 'v1')}", ng-click="filterProjects('v1')") + a(href) #{translate("v1_projects")} li.separator h2 #{translate("folders")} li.tag( @@ -62,6 +65,11 @@ ) span.name {{tag.name}} span.subdued ({{tag.project_ids.length}}) + span.v1-badge( + ng-if="tag.isV1", + ng-cloak, + aria-label=translate("v1_badge") + ) span.dropdown.tag-menu(dropdown) a.dropdown-toggle( href="#", diff --git a/services/web/app/views/project/list/v1-item.pug b/services/web/app/views/project/list/v1-item.pug new file mode 100644 index 0000000000..3a5e86e791 --- /dev/null +++ b/services/web/app/views/project/list/v1-item.pug @@ -0,0 +1,11 @@ +.col-xs-8 + span.v1-badge(aria-label=translate("v1_badge")) + span + if settings.overleaf && settings.overleaf.host + a.projectName( + href=settings.overleaf.host + "/{{project.id}}" + stop-propagation="click" + ) {{project.name}} + +.col-xs-4 + span.last-modified {{project.lastUpdated | formatDate}} \ No newline at end of file diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee index 577a3a0e75..43b4dac5b1 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee @@ -35,7 +35,7 @@ define [ url = ace.config._moduleUrl(args...) + "?fingerprint=#{window.aceFingerprint}" return url - App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage, $cacheFactory, labels, graphics, preamble, $http) -> + App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage, $cacheFactory, labels, graphics, preamble, $http, $q) -> monkeyPatchSearch($rootScope, $compile) return { @@ -97,7 +97,7 @@ define [ if scope.spellCheck # only enable spellcheck when explicitly required spellCheckCache = $cacheFactory("spellCheck-#{scope.name}", {capacity: 1000}) - spellCheckManager = new SpellCheckManager(scope, editor, element, spellCheckCache, $http) + spellCheckManager = new SpellCheckManager(scope, editor, element, spellCheckCache, $http, $q) undoManager = new UndoManager(scope, editor, element) highlightsManager = new HighlightsManager(scope, editor, element) cursorPositionManager = new CursorPositionManager(scope, editor, element, localStorage) @@ -356,6 +356,7 @@ define [ session.setOption("useWorker", scope.syntaxValidation); # now attach session to editor + editor.setReadOnly(true) # set to readonly until document change handlers are attached editor.setSession(session) doc = session.getDocument() @@ -364,6 +365,8 @@ define [ editor.initing = true sharejs_doc.attachToAce(editor) editor.initing = false + # now ready to edit document + editor.setReadOnly(scope.readOnly) # respect the readOnly setting, normally false resetScrollMargins() diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee index 24a524b4b6..170d75ce60 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee @@ -149,7 +149,7 @@ define [ lastCharIsBackslash = lineUpToCursor.slice(-1) == "\\" lastTwoChars = lineUpToCursor.slice(-2) # Don't offer autocomplete on double-backslash, backslash-colon, etc - if lastTwoChars.match(/^\\[^a-z]$/) + if lastTwoChars.match(/^\\[^a-zA-Z]$/) @editor?.completer?.detach?() return if commandName in ['begin', 'end'] @@ -229,8 +229,9 @@ define [ 99999 ) ) + if lineBeyondCursor - if partialCommandMatch = lineBeyondCursor.match(/^([a-z0-9]+)\{/) + if partialCommandMatch = lineBeyondCursor.match(/^([a-zA-Z0-9]+)\{/) # We've got a partial command after the cursor commandTail = partialCommandMatch[1] # remove rest of the partial command, right of cursor diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/Helpers.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/Helpers.coffee index 7beb41debd..c3d5ef56ba 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/Helpers.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/Helpers.coffee @@ -17,8 +17,8 @@ define [ # \includegraphics[width=\textwidth]{.. # should not match the \textwidth. blankArguments = lineUpToCursor.replace /\[([^\]]*)\]/g, (args) -> - Array(args.length+1).join('.') - if m = blankArguments.match(/(\\[^\\]+)$/) + Array(args.length + 1).join('.') + if m = blankArguments.match(/(\\[^\\]*)$/) return m.index else return -1 diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee index 5d420a29b4..acbd636531 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee @@ -5,9 +5,9 @@ define [ Range = ace.require("ace/range").Range class SpellCheckManager - constructor: (@$scope, @editor, @element, @cache, @$http) -> + constructor: (@$scope, @editor, @element, @cache, @$http, @$q) -> $(document.body).append @element.find(".spell-check-menu") - + @inProgressRequest = null @updatedLines = [] @highlightedWordManager = new HighlightedWordManager(@editor) @@ -23,8 +23,8 @@ define [ @editor.on "changeSession", (e) => @highlightedWordManager.reset() - # if @inProgressRequest? - # @inProgressRequest.abort() + if @inProgressRequest? + @inProgressRequest.abort() if @$scope.spellCheckEnabled and @$scope.spellCheckLanguage and @$scope.spellCheckLanguage != "" @runSpellCheckSoon(200) @@ -235,11 +235,18 @@ define [ apiRequest: (endpoint, data, callback = (error, result) ->)-> data.token = window.user.id data._csrf = window.csrfToken - @$http.post("/spelling" + endpoint, data) + # use angular timeout option to cancel request if doc is changed + requestHandler = @$q.defer() + options = {timeout: requestHandler.promise} + httpRequest = @$http.post("/spelling" + endpoint, data, options) .then (response) => callback(null, response.data) .catch (response) => callback(new Error('api failure')) + # provide a method to cancel the request + abortRequest = () -> + requestHandler.resolve() + return { abort: abortRequest } blacklistedCommandRegex: /// \\ # initial backslash diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index e2bb51a0fd..17afd8bbcb 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -85,7 +85,11 @@ define [ isTimeNonMonotonic = timeSinceLastCompile < 0 if isTimeNonMonotonic || timeSinceLastCompile >= AUTO_COMPILE_TIMEOUT - if (!ide.$scope.hasLintingError) + # If user has code check disabled, it is likely because they have + # linting errors that they are ignoring. Therefore it doesn't make sense + # to block auto compiles. It also causes problems where server-provided + # linting errors aren't cleared after typing + if (ide.$scope.settings.syntaxValidation and !ide.$scope.hasLintingError) $scope.recompile(isAutoCompileOnChange: true) else # Extend remainder of timeout diff --git a/services/web/public/coffee/main/project-list/project-list.coffee b/services/web/public/coffee/main/project-list/project-list.coffee index 8c39df060f..1d81504c74 100644 --- a/services/web/public/coffee/main/project-list/project-list.coffee +++ b/services/web/public/coffee/main/project-list/project-list.coffee @@ -116,6 +116,10 @@ define [ if $scope.filter == "shared" and project.accessLevel == "owner" visible = false + # Hide projects from V1 if we only want to see shared projects + if $scope.filter == "shared" and project.isV1Project + visible = false + # Hide projects we don't own if we only want to see owned projects if $scope.filter == "owned" and project.accessLevel != "owner" visible = false @@ -129,6 +133,9 @@ define [ if project.archived visible = false + if $scope.filter == "v1" and !project.isV1Project + visible = false + if visible $scope.visibleProjects.push project else diff --git a/services/web/public/stylesheets/_style_includes.less b/services/web/public/stylesheets/_style_includes.less index a5c7589ef0..54539a4cb4 100644 --- a/services/web/public/stylesheets/_style_includes.less +++ b/services/web/public/stylesheets/_style_includes.less @@ -78,6 +78,7 @@ @import "app/invite.less"; @import "app/review-features-page.less"; @import "app/error-pages.less"; +@import "app/v1-badge.less"; @import "../js/libs/pdfListView/TextLayer.css"; @import "../js/libs/pdfListView/AnnotationsLayer.css"; diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index 1568915296..1ca170ff89 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -366,6 +366,11 @@ ul.project-list { border-top-left-radius: 0; border-bottom-left-radius: 0; } + + .v1-badge { + margin-right: 9px; + margin-left: 7px; + } } i.tablesort { padding-left: 8px; diff --git a/services/web/public/stylesheets/app/v1-badge.less b/services/web/public/stylesheets/app/v1-badge.less new file mode 100644 index 0000000000..ced9d04c81 --- /dev/null +++ b/services/web/public/stylesheets/app/v1-badge.less @@ -0,0 +1,10 @@ +.v1-badge { + &:extend(.label); + &:extend(.label-default); + vertical-align: 11%; + padding: 1px 3px; + margin: 0 6px; + &:before { + content: "V1"; + } +} \ No newline at end of file diff --git a/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee index 498090f790..35176acd4b 100644 --- a/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee @@ -66,6 +66,9 @@ describe "ProjectController", -> protectTokens: sinon.stub() @CollaboratorsHandler = userIsTokenMember: sinon.stub().callsArgWith(2, null, false) + @Modules = + hooks: + fire: sinon.stub() @ProjectController = SandboxedModule.require modulePath, requires: "settings-sharelatex":@settings "logger-sharelatex": @@ -93,6 +96,7 @@ describe "ProjectController", -> "../Analytics/AnalyticsManager": @AnalyticsManager "../TokenAccess/TokenAccessHandler": @TokenAccessHandler "../Collaborators/CollaboratorsHandler": @CollaboratorsHandler + "../../infrastructure/Modules": @Modules @projectName = "£12321jkj9ujkljds" @req = @@ -263,6 +267,7 @@ describe "ProjectController", -> @TagsHandler.getAllTags.callsArgWith(1, null, @tags, {}) @NotificationsHandler.getUserNotifications = sinon.stub().callsArgWith(1, null, @notifications, {}) @ProjectGetter.findAllUsersProjects.callsArgWith(2, null, @allProjects) + @Modules.hooks.fire.withArgs('findAllV1Projects', @user._id).yields(undefined) # Without integration module hook, cb returns undefined it "should render the project/list page", (done)-> @res.render = (pageName, opts)=> @@ -295,6 +300,53 @@ describe "ProjectController", -> done() @ProjectController.projectListPage @req, @res + describe 'with overleaf-integration-web-module hook', -> + beforeEach -> + @V1Response = + projects: [ + { id: '123mockV1Id', title: 'mock title', updated_at: 1509616411, removed: false, archived: false } + { id: '456mockV1Id', title: 'mock title 2', updated_at: 1509616411, removed: true, archived: false } + ], + tags: [ + { name: 'mock tag', project_ids: ['123mockV1Id'] } + ] + @Modules.hooks.fire.withArgs('findAllV1Projects', @user._id).yields(null, [@V1Response]) # Need to wrap response in array, as multiple hooks could fire + + it 'should include V1 projects', (done) -> + @res.render = (pageName, opts) => + opts.projects.length.should.equal ( + @projects.length + + @collabertions.length + + @readOnly.length + + @tokenReadAndWrite.length + + @tokenReadOnly.length + + @V1Response.projects.length + ) + opts.projects.forEach (p) -> + # Check properties correctly mapped from V1 + expect(p).to.have.property 'id' + expect(p).to.have.property 'name' + expect(p).to.have.property 'lastUpdated' + expect(p).to.have.property 'accessLevel' + expect(p).to.have.property 'archived' + done() + @ProjectController.projectListPage @req, @res + + it 'should include V1 tags', (done) -> + @res.render = (pageName, opts) => + opts.tags.length.should.equal (@tags.length + @V1Response.tags.length) + opts.tags.forEach (t) -> + expect(t).to.have.property 'name' + expect(t).to.have.property 'project_ids' + done() + @ProjectController.projectListPage @req, @res + + it 'should have isShowingV1Projects flag', (done) -> + @res.render = (pageName, opts) => + opts.isShowingV1Projects.should.equal true + done() + @ProjectController.projectListPage @req, @res + describe "projectListPage with duplicate projects", -> beforeEach -> @@ -338,6 +390,7 @@ describe "ProjectController", -> @TagsHandler.getAllTags.callsArgWith(1, null, @tags, {}) @NotificationsHandler.getUserNotifications = sinon.stub().callsArgWith(1, null, @notifications, {}) @ProjectGetter.findAllUsersProjects.callsArgWith(2, null, @allProjects) + @Modules.hooks.fire.withArgs('findAllV1Projects', @user._id).yields(undefined) # Without integration module hook, cb returns undefined it "should render the project/list page", (done)-> @res.render = (pageName, opts)=> diff --git a/services/web/test/UnitTests/coffee/User/UserControllerTests.coffee b/services/web/test/UnitTests/coffee/User/UserControllerTests.coffee index a71fe4bb91..c358f35b22 100644 --- a/services/web/test/UnitTests/coffee/User/UserControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/User/UserControllerTests.coffee @@ -187,6 +187,7 @@ describe "UserController", -> describe "updateUserSettings", -> beforeEach -> @newEmail = "hello@world.com" + @req.externalAuthenticationSystemUsed = sinon.stub().returns(false) it "should call save", (done)-> @req.body = {} @@ -280,10 +281,7 @@ describe "UserController", -> beforeEach -> @UserUpdater.changeEmailAddress.callsArgWith(2) @newEmail = 'someone23@example.com' - @settings.ldap = {active: true} - - afterEach -> - delete @settings.ldap + @req.externalAuthenticationSystemUsed = sinon.stub().returns(true) it 'should not set a new email', (done) -> @req.body.email = @newEmail diff --git a/services/web/test/smoke/coffee/SmokeTests.coffee b/services/web/test/smoke/coffee/SmokeTests.coffee index 0e6f7d6244..e710acddec 100644 --- a/services/web/test/smoke/coffee/SmokeTests.coffee +++ b/services/web/test/smoke/coffee/SmokeTests.coffee @@ -33,23 +33,19 @@ describe "Opening", -> return done(err) logger.log "smoke test: clearing rate limit " require("../../../app/js/infrastructure/RateLimiter.js").clearRateLimit "open-project", "#{Settings.smokeTest.projectId}:#{Settings.smokeTest.userId}", -> - logger.log "smoke test: hitting /register" + logger.log "smoke test: hitting dev/csrf" command = """ - curl -H "X-Forwarded-Proto: https" -c #{cookeFilePath} #{buildUrl('register')} + curl -H "X-Forwarded-Proto: https" -c #{cookeFilePath} #{buildUrl('dev/csrf')} """ child.exec command, (err, stdout, stderr)-> if err? then done(err) - csrfMatches = stdout.match("") - if !csrfMatches? - logger.err stdout:stdout, "smoke test: does not have csrf token" - return done("smoke test: does not have csrf token") - csrf = csrfMatches[1] + csrf = stdout logger.log "smoke test: converting cookie file 1" convertCookieFile (err) -> return done(err) if err? - logger.log "smoke test: hitting /register with csrf" + logger.log "smoke test: hitting /login with csrf" command = """ - curl -c #{cookeFilePath} -H "Content-Type: application/json" -H "X-Forwarded-Proto: https" -d '{"_csrf":"#{csrf}", "email":"#{Settings.smokeTest.user}", "password":"#{Settings.smokeTest.password}"}' #{buildUrl('register')} + curl -c #{cookeFilePath} -H "Content-Type: application/json" -H "X-Forwarded-Proto: https" -d '{"_csrf":"#{csrf}", "email":"#{Settings.smokeTest.user}", "password":"#{Settings.smokeTest.password}"}' #{buildUrl('login')} """ child.exec command, (err) -> return done(err) if err?