From bdc741520ea2e48adeb8de5907c6ad4838f3f6de Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Mon, 20 Apr 2015 11:44:07 -0700 Subject: [PATCH] Disable inclusion of User.accessTokens --- common/models/user.json | 5 +- .../common/models/blog.json | 18 ++ .../common/models/my-user.json | 18 ++ .../common/models/post.json | 21 +++ .../user-integration-app/server/config.json | 15 ++ .../server/datasources.json | 11 ++ .../server/model-config.json | 58 ++++++ .../user-integration-app/server/server.js | 10 ++ test/user.integration.js | 166 ++++++++++++++++++ 9 files changed, 321 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/user-integration-app/common/models/blog.json create mode 100644 test/fixtures/user-integration-app/common/models/my-user.json create mode 100644 test/fixtures/user-integration-app/common/models/post.json create mode 100644 test/fixtures/user-integration-app/server/config.json create mode 100644 test/fixtures/user-integration-app/server/datasources.json create mode 100644 test/fixtures/user-integration-app/server/model-config.json create mode 100644 test/fixtures/user-integration-app/server/server.js create mode 100644 test/user.integration.js diff --git a/common/models/user.json b/common/models/user.json index 4f8d63d7..be60d9d8 100644 --- a/common/models/user.json +++ b/common/models/user.json @@ -90,7 +90,10 @@ "accessTokens": { "type": "hasMany", "model": "AccessToken", - "foreignKey": "userId" + "foreignKey": "userId", + "options": { + "disableInclude": true + } } } } diff --git a/test/fixtures/user-integration-app/common/models/blog.json b/test/fixtures/user-integration-app/common/models/blog.json new file mode 100644 index 00000000..02312823 --- /dev/null +++ b/test/fixtures/user-integration-app/common/models/blog.json @@ -0,0 +1,18 @@ +{ + "name": "blog", + "base": "PersistedModel", + "properties": { + "title": { + "type": "string" + }, + "content": { + "type": "string" + } + }, + "relations": { + "user": { + "type": "belongsTo", + "model": "myUser" + } + } +} \ No newline at end of file diff --git a/test/fixtures/user-integration-app/common/models/my-user.json b/test/fixtures/user-integration-app/common/models/my-user.json new file mode 100644 index 00000000..b11877b0 --- /dev/null +++ b/test/fixtures/user-integration-app/common/models/my-user.json @@ -0,0 +1,18 @@ +{ + "name": "myUser", + "base": "User", + "relations": { + "blogs": { + "model": "blog", + "type": "hasMany", + "foreignKey": "userId" + } + }, + "acls": [ + { + "permission": "ALLOW", + "principalType": "ROLE", + "principalId": "$owner" + } + ] +} \ No newline at end of file diff --git a/test/fixtures/user-integration-app/common/models/post.json b/test/fixtures/user-integration-app/common/models/post.json new file mode 100644 index 00000000..e6990891 --- /dev/null +++ b/test/fixtures/user-integration-app/common/models/post.json @@ -0,0 +1,21 @@ +{ + "name": "post", + "base": "PersistedModel", + "properties": { + "title": { + "type": "string" + }, + "content": { + "type": "string" + }, + "notes": { + "type": "string" + } + }, + "relations": { + "user": { + "type": "belongsTo", + "model": "User" + } + } +} \ No newline at end of file diff --git a/test/fixtures/user-integration-app/server/config.json b/test/fixtures/user-integration-app/server/config.json new file mode 100644 index 00000000..c7cce73e --- /dev/null +++ b/test/fixtures/user-integration-app/server/config.json @@ -0,0 +1,15 @@ +{ + "port": 3000, + "host": "0.0.0.0", + "cookieSecret": "2d13a01d-44fb-455c-80cb-db9cb3cd3cd0", + "remoting": { + "json": { + "limit": "1kb", + "strict": false + }, + "urlencoded": { + "limit": "8kb" + } + }, + "legacyExplorer": false +} \ No newline at end of file diff --git a/test/fixtures/user-integration-app/server/datasources.json b/test/fixtures/user-integration-app/server/datasources.json new file mode 100644 index 00000000..b024f6f3 --- /dev/null +++ b/test/fixtures/user-integration-app/server/datasources.json @@ -0,0 +1,11 @@ +{ + "db": { + "connector": "memory" + }, + "mail": { + "connector": "mail", + "transports": [ + {"type": "STUB"} + ] + } +} \ No newline at end of file diff --git a/test/fixtures/user-integration-app/server/model-config.json b/test/fixtures/user-integration-app/server/model-config.json new file mode 100644 index 00000000..b8181828 --- /dev/null +++ b/test/fixtures/user-integration-app/server/model-config.json @@ -0,0 +1,58 @@ +{ + "_meta": { + "sources": [ + "../common/models", + "./models" + ] + }, + "Email": { + "dataSource": "mail", + "public": false + }, + "User": { + "dataSource": "db", + "public": true, + "relations": { + "posts": { + "model": "post", + "type": "hasMany", + "foreignKey": "userId" + } + }, + "acls": [ + { + "permission": "ALLOW", + "principalType": "ROLE", + "principalId": "$owner" + } + ] + }, + "AccessToken": { + "dataSource": "db", + "public": false + }, + "ACL": { + "dataSource": "db", + "public": false + }, + "RoleMapping": { + "dataSource": "db", + "public": false + }, + "Role": { + "dataSource": "db", + "public": false + }, + "myUser": { + "dataSource": "db", + "public": true + }, + "blog": { + "dataSource": "db", + "public": true + }, + "post": { + "dataSource": "db", + "public": true + } +} diff --git a/test/fixtures/user-integration-app/server/server.js b/test/fixtures/user-integration-app/server/server.js new file mode 100644 index 00000000..1d3d6720 --- /dev/null +++ b/test/fixtures/user-integration-app/server/server.js @@ -0,0 +1,10 @@ +var loopback = require('../../../../index'); +var boot = require('loopback-boot'); +var app = module.exports = loopback(); +app.enableAuth(); +boot(app, __dirname); +app.use(loopback.token({model: app.models.AccessToken})); +var apiPath = '/api'; +app.use(apiPath, loopback.rest()); +app.use(loopback.urlNotFound()); +app.use(loopback.errorHandler()); diff --git a/test/user.integration.js b/test/user.integration.js new file mode 100644 index 00000000..14dfe2ef --- /dev/null +++ b/test/user.integration.js @@ -0,0 +1,166 @@ +/*jshint -W030 */ +var loopback = require('../'); +var lt = require('loopback-testing'); +var path = require('path'); +var SIMPLE_APP = path.join(__dirname, 'fixtures', 'user-integration-app'); +var app = require(path.join(SIMPLE_APP, 'server/server.js')); +var expect = require('chai').expect; + +describe('users - integration', function() { + + lt.beforeEach.withApp(app); + + before(function(done) { + // HACK: [rfeng] We have to reset the relations as they are polluted by + // other tests + app.models.User.hasMany(app.models.post); + app.models.User.hasMany(app.models.AccessToken, + {options: {disableInclude: true}}); + app.models.AccessToken.belongsTo(app.models.User); + app.models.User.destroyAll(function(err) { + if (err) return done(err); + app.models.post.destroyAll(function(err) { + if (err) return done(err); + app.models.blog.destroyAll(function(err) { + if (err) return done(err); + done(); + }); + }); + }); + }); + + describe('base-user', function() { + var userId; + var accessToken; + + it('should create a new user', function(done) { + var url = '/api/users'; + + this.post(url) + .send({username: 'x', email: 'x@y.com', password: 'x'}) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body.id).to.exist; + userId = res.body.id; + done(); + }); + }); + + it('should log into the user', function(done) { + var url = '/api/users/login'; + + this.post(url) + .send({username: 'x', email: 'x@y.com', password: 'x'}) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body.id).to.exist; + accessToken = res.body.id; + done(); + }); + }); + + it('should create post for a given user', function(done) { + var url = '/api/users/' + userId + '/posts?access_token=' + accessToken; + this.post(url) + .send({title: 'T1', content: 'C1'}) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body.title).to.be.eql('T1'); + expect(res.body.content).to.be.eql('C1'); + expect(res.body.userId).to.be.eql(userId); + done(); + }); + }); + + // FIXME: [rfeng] The test is passing if run alone. But it fails with + // `npm test` as the loopback models are polluted by other tests + it('should prevent access tokens from being included', function(done) { + var url = '/api/posts?filter={"include":{"user":"accessTokens"}}'; + this.get(url) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body).to.have.property('length', 1); + var post = res.body[0]; + expect(post.user).to.have.property('username', 'x'); + expect(post.user).to.not.have.property('accessTokens'); + done(); + }); + }); + }); + + describe('sub-user', function() { + var userId; + var accessToken; + + it('should create a new user', function(done) { + var url = '/api/myUsers'; + + this.post(url) + .send({username: 'x', email: 'x@y.com', password: 'x'}) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body.id).to.exist; + userId = res.body.id; + done(); + }); + }); + + it('should log into the user', function(done) { + var url = '/api/myUsers/login'; + + this.post(url) + .send({username: 'x', email: 'x@y.com', password: 'x'}) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body.id).to.exist; + accessToken = res.body.id; + done(); + }); + }); + + it('should create blog for a given user', function(done) { + var url = '/api/myUsers/' + userId + '/blogs?access_token=' + accessToken; + this.post(url) + .send({title: 'T1', content: 'C1'}) + .expect(200, function(err, res) { + if (err) { + console.error(err); + return done(err); + } + expect(res.body.title).to.be.eql('T1'); + expect(res.body.content).to.be.eql('C1'); + expect(res.body.userId).to.be.eql(userId); + done(); + }); + }); + + it('should prevent access tokens from being included', function(done) { + var url = '/api/blogs?filter={"include":{"user":"accessTokens"}}'; + this.get(url) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body).to.have.property('length', 1); + var blog = res.body[0]; + expect(blog.user).to.have.property('username', 'x'); + expect(blog.user).to.not.have.property('accessTokens'); + done(); + }); + }); + }); + +}); +