Bläddra i källkod

Start acceptance tests for token-based access

Shane Kilkelly 9 år sedan
förälder
incheckning
b5bed1837e

+ 172 - 0
services/web/test/acceptance/coffee/TokenAccessTests.coffee

@@ -0,0 +1,172 @@
+expect = require("chai").expect
+async = require("async")
+User = require "./helpers/User"
+request = require "./helpers/request"
+settings = require "settings-sharelatex"
+
+try_read_access = (user, project_id, test, callback) ->
+	async.series [
+		(cb) ->
+			user.request.get "/project/#{project_id}", (error, response, body) ->
+				return cb(error) if error?
+				test(response, body)
+				cb()
+		(cb) ->
+			user.request.get "/project/#{project_id}/download/zip", (error, response, body) ->
+				return cb(error) if error?
+				test(response, body)
+				cb()
+	], callback
+
+try_read_only_token_access = (user, token, test, callback) ->
+	async.series [
+		(cb) ->
+			user.request.get "/read/#{token}", (error, response, body) ->
+				return cb(error) if error?
+				test(response, body)
+				cb()
+	], callback
+
+try_read_and_write_token_access = (user, token, test, callback) ->
+	async.series [
+		(cb) ->
+			user.request.get "/read/#{token}", (error, response, body) ->
+				return cb(error) if error?
+				test(response, body)
+				cb()
+	], callback
+
+try_content_access = (user, project_id, test, callback) ->
+	# The real-time service calls this end point to determine the user's 
+	# permissions.
+	if user.id?
+		user_id = user.id
+	else
+		user_id = "anonymous-user"
+	request.post {
+		url: "/project/#{project_id}/join"
+		qs: {user_id}
+		auth:
+			user: settings.apis.web.user
+			pass: settings.apis.web.pass
+			sendImmediately: true
+		json: true
+		jar: false
+	}, (error, response, body) ->
+		return callback(error) if error?
+		test(response, body)
+		callback()
+
+expect_content_write_access = (user, project_id, callback) ->
+	try_content_access(user, project_id, (response, body) ->
+		expect(body.privilegeLevel).to.be.oneOf ["readAndWrite"]
+	, callback)
+
+expect_content_read_access = (user, project_id, callback) ->
+	try_content_access(user, project_id, (response, body) ->
+		expect(body.privilegeLevel).to.be.oneOf ["readOnly"]
+	, callback)
+
+expect_read_only_access = (user, project_id, token, callback) ->
+	async.series [
+		(cb) ->
+			try_read_only_token_access(user, token, (response, body) ->
+				expect(response.statusCode).to.be.oneOf [200, 204]
+			, cb)
+		(cb) ->
+			try_content_access(user, project_id, (response, body) ->
+				expect(body.privilegeLevel).to.be.oneOf ["readOnly"]
+			, cb)
+	], callback
+
+expect_read_and_write_access = (user, project_id, token, callback) ->
+	async.series [
+		(cb) ->
+			try_read_and_write_token_access(user, token, (response, body) ->
+				expect(response.statusCode).to.be.oneOf [200, 204]
+			, cb)
+		(cb) ->
+			try_content_access(user, project_id, (response, body) ->
+				expect(body.privilegeLevel).to.be.oneOf ["readAndWrite"]
+			, cb)
+	], callback
+
+
+
+
+
+describe 'TokenAccess', ->
+	before (done) ->
+		@timeout(90000)
+		@owner = new User()
+		@other1 = new User()
+		@other2 = new User()
+		@anon = new User()
+		async.parallel [
+			(cb) => @owner.login cb
+			(cb) => @other1.login cb
+			(cb) => @other2.login cb
+			(cb) => @anon.getCsrfToken cb
+		], done
+
+	describe 'read-only token', ->
+		before (done) ->
+			@owner.createProject 'token-ro-test#{Math.random()}', (err, project_id) =>
+				return done(err) if err?
+				@project_id = project_id
+				@owner.makeTokenBased @project_id, (err) =>
+					return done(err) if err?
+					@owner.getProject @project_id, (err, project) =>
+						return done(err) if err?
+						@tokens = project.tokens
+						console.log ">> ", @project_id, @tokens, project.publicAccesLevel
+						done()
+
+		it 'should deny access before the token is used', (done) ->
+			try_read_access(@other1, @project_id, (response, body) =>
+				expect(response.statusCode).to.equal 302
+				expect(body).to.match /.*\/restricted.*/
+			, done)
+
+		it 'should allow the user to access project via read-only token url', (done) ->
+			try_read_only_token_access(@other1, @tokens.readOnly, (response, body) =>
+				expect(response.statusCode).to.equal 200
+			, done)
+
+		it 'should allow the user to join the project with read-only access', (done) ->
+			try_content_access(@other1, @project_id, (response, body) =>
+				expect(body.privilegeLevel).to.equal 'readOnly'
+			, done)
+
+		describe 'made private again', ->
+			before (done) ->
+				@owner.makePrivate @project_id, () -> setTimeout(done, 1000)
+
+			it 'should deny access to project', (done) ->
+				try_read_access(@other1, @project_id, (response, body) =>
+					expect(response.statusCode).to.equal 302
+					expect(body).to.match /.*\/restricted.*/
+				, done)
+
+			it 'should not allow the user to access read-only token', (done) ->
+				try_read_only_token_access(@other1, @tokens.readOnly, (response, body) =>
+					expect(response.statusCode).to.equal 404
+				, done)
+
+			it 'should not allow the user to join the project', (done) ->
+				try_content_access(@other1, @project_id, (response, body) =>
+					expect(body.privilegeLevel).to.equal false
+				, done)
+
+
+	# describe 'anonymous read-only token', ->
+	# 	beforeEach ->
+
+	# 	describe 'made private again', ->
+	# 		beforeEach ->
+
+	# describe 'read-and-write token', ->
+	# 	beforeEach ->
+
+	# 	describe 'made private again', ->
+	# 		beforeEach ->

+ 21 - 0
services/web/test/acceptance/coffee/helpers/User.coffee

@@ -93,6 +93,9 @@ class User
 					callback(err)
 					callback(err)
 				db.users.remove {_id: ObjectId(user_id)}, callback
 				db.users.remove {_id: ObjectId(user_id)}, callback
 
 
+	getProject: (project_id, callback = (error, project)->) ->
+		db.projects.findOne {_id: ObjectId(project_id.toString())}, callback
+
 	createProject: (name, callback = (error, project_id) ->) ->
 	createProject: (name, callback = (error, project_id) ->) ->
 		@request.post {
 		@request.post {
 			url: "/project/new",
 			url: "/project/new",
@@ -138,6 +141,24 @@ class User
 			return callback(error) if error?
 			return callback(error) if error?
 			callback(null)
 			callback(null)
 
 
+	makePrivate: (project_id, callback = (error) ->) ->
+		@request.post {
+			url: "/project/#{project_id}/settings/admin",
+			json:
+				publicAccessLevel: 'private'
+		}, (error, response, body) ->
+			return callback(error) if error?
+			callback(null)
+
+	makeTokenBased: (project_id, callback = (error) ->) ->
+		@request.post {
+			url: "/project/#{project_id}/settings/admin",
+			json:
+				publicAccessLevel: 'tokenBased'
+		}, (error, response, body) ->
+			return callback(error) if error?
+			callback(null)
+
 	getCsrfToken: (callback = (error) ->) ->
 	getCsrfToken: (callback = (error) ->) ->
 		@request.get {
 		@request.get {
 			url: "/register"
 			url: "/register"