Merge pull request #332 from ParsePlatform/nlutsenko.login.files
Fixed missing url for files on user login.
This commit is contained in:
@@ -64,6 +64,22 @@ describe('Parse.User testing', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("user login with files", (done) => {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let file = new Parse.File("yolo.txt", [1,2,3], "text/plain");
|
||||||
|
file.save().then((file) => {
|
||||||
|
return Parse.User.signUp("asdf", "zxcv", { "file" : file });
|
||||||
|
}).then(() => {
|
||||||
|
return Parse.User.logIn("asdf", "zxcv");
|
||||||
|
}).then((user) => {
|
||||||
|
let fileAgain = user.get('file');
|
||||||
|
ok(fileAgain.name());
|
||||||
|
ok(fileAgain.url());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("become", (done) => {
|
it("become", (done) => {
|
||||||
var user = null;
|
var user = null;
|
||||||
var sessionToken = null;
|
var sessionToken = null;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ function Config(applicationId, mount) {
|
|||||||
|
|
||||||
this.applicationId = applicationId;
|
this.applicationId = applicationId;
|
||||||
this.collectionPrefix = cacheInfo.collectionPrefix || '';
|
this.collectionPrefix = cacheInfo.collectionPrefix || '';
|
||||||
this.database = DatabaseAdapter.getDatabaseConnection(applicationId);
|
|
||||||
this.masterKey = cacheInfo.masterKey;
|
this.masterKey = cacheInfo.masterKey;
|
||||||
this.clientKey = cacheInfo.clientKey;
|
this.clientKey = cacheInfo.clientKey;
|
||||||
this.javascriptKey = cacheInfo.javascriptKey;
|
this.javascriptKey = cacheInfo.javascriptKey;
|
||||||
@@ -21,6 +20,10 @@ function Config(applicationId, mount) {
|
|||||||
this.restAPIKey = cacheInfo.restAPIKey;
|
this.restAPIKey = cacheInfo.restAPIKey;
|
||||||
this.fileKey = cacheInfo.fileKey;
|
this.fileKey = cacheInfo.fileKey;
|
||||||
this.facebookAppIds = cacheInfo.facebookAppIds;
|
this.facebookAppIds = cacheInfo.facebookAppIds;
|
||||||
|
|
||||||
|
this.database = DatabaseAdapter.getDatabaseConnection(applicationId);
|
||||||
|
this.filesController = cacheInfo.filesController;
|
||||||
|
|
||||||
this.mount = mount;
|
this.mount = mount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ export class FilesController {
|
|||||||
getHandler() {
|
getHandler() {
|
||||||
return (req, res) => {
|
return (req, res) => {
|
||||||
let config = new Config(req.params.appId);
|
let config = new Config(req.params.appId);
|
||||||
this._filesAdapter.getFileDataAsync(config, req.params.filename).then((data) => {
|
let filename = req.params.filename;
|
||||||
|
this._filesAdapter.getFileDataAsync(config, filename).then((data) => {
|
||||||
res.status(200);
|
res.status(200);
|
||||||
var contentType = mime.lookup(req.params.filename);
|
var contentType = mime.lookup(filename);
|
||||||
res.set('Content-type', contentType);
|
res.set('Content-type', contentType);
|
||||||
res.end(data);
|
res.end(data);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
@@ -63,17 +64,45 @@ export class FilesController {
|
|||||||
let filename = rack() + '_' + req.params.filename + extension;
|
let filename = rack() + '_' + req.params.filename + extension;
|
||||||
this._filesAdapter.createFileAsync(req.config, filename, req.body).then(() => {
|
this._filesAdapter.createFileAsync(req.config, filename, req.body).then(() => {
|
||||||
res.status(201);
|
res.status(201);
|
||||||
var location = this._filesAdapter.getFileLocation(req.config, req, filename);
|
var location = this._filesAdapter.getFileLocation(req.config, filename);
|
||||||
res.set('Location', location);
|
res.set('Location', location);
|
||||||
res.json({ url: location, name: filename });
|
res.json({ url: location, name: filename });
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.log(error);
|
|
||||||
next(new Parse.Error(Parse.Error.FILE_SAVE_ERROR,
|
next(new Parse.Error(Parse.Error.FILE_SAVE_ERROR,
|
||||||
'Could not store file.'));
|
'Could not store file.'));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find file references in REST-format object and adds the url key
|
||||||
|
* with the current mount point and app id.
|
||||||
|
* Object may be a single object or list of REST-format objects.
|
||||||
|
*/
|
||||||
|
expandFilesInObject(config, object) {
|
||||||
|
if (object instanceof Array) {
|
||||||
|
object.map((obj) => this.expandFilesInObject(config, obj));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof object !== 'object') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let key in object) {
|
||||||
|
let fileObject = object[key];
|
||||||
|
if (fileObject && fileObject['__type'] === 'File') {
|
||||||
|
if (fileObject['url']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let filename = fileObject['name'];
|
||||||
|
if (filename.indexOf('tfss-') === 0) {
|
||||||
|
fileObject['url'] = 'http://files.parsetfss.com/' + config.fileKey + '/' + encodeURIComponent(filename);
|
||||||
|
} else {
|
||||||
|
fileObject['url'] = this._filesAdapter.getFileLocation(config, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getExpressRouter() {
|
getExpressRouter() {
|
||||||
let router = express.Router();
|
let router = express.Router();
|
||||||
router.get('/files/:appId/:filename', this.getHandler());
|
router.get('/files/:appId/:filename', this.getHandler());
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class FilesAdapter {
|
|||||||
|
|
||||||
getFileDataAsync(config, filename) { }
|
getFileDataAsync(config, filename) { }
|
||||||
|
|
||||||
getFileLocation(config, request, filename) { }
|
getFileLocation(config, filename) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FilesAdapter;
|
export default FilesAdapter;
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
// Requires the database adapter to be based on mongoclient
|
// Requires the database adapter to be based on mongoclient
|
||||||
|
|
||||||
import { GridStore } from 'mongodb';
|
import { GridStore } from 'mongodb';
|
||||||
|
|
||||||
import * as Path from 'path';
|
|
||||||
import { FilesAdapter } from './FilesAdapter';
|
import { FilesAdapter } from './FilesAdapter';
|
||||||
|
|
||||||
class GridStoreAdapter extends FilesAdapter {
|
class GridStoreAdapter extends FilesAdapter {
|
||||||
@@ -33,10 +31,8 @@ class GridStoreAdapter extends FilesAdapter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getFileLocation(config, request, filename) {
|
getFileLocation(config, filename) {
|
||||||
return (request.protocol + '://' + request.get('host') +
|
return (config.mount + '/files/' + config.applicationId + '/' + encodeURIComponent(filename));
|
||||||
Path.dirname(request.originalUrl) + '/' + config.applicationId +
|
|
||||||
'/' + encodeURIComponent(filename));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
var Parse = require('parse/node').Parse;
|
var Parse = require('parse/node').Parse;
|
||||||
|
|
||||||
|
import { default as FilesController } from './Controllers/FilesController';
|
||||||
|
|
||||||
// restOptions can include:
|
// restOptions can include:
|
||||||
// skip
|
// skip
|
||||||
// limit
|
// limit
|
||||||
@@ -316,35 +318,35 @@ RestQuery.prototype.replaceDontSelect = function() {
|
|||||||
RestQuery.prototype.runFind = function() {
|
RestQuery.prototype.runFind = function() {
|
||||||
return this.config.database.find(
|
return this.config.database.find(
|
||||||
this.className, this.restWhere, this.findOptions).then((results) => {
|
this.className, this.restWhere, this.findOptions).then((results) => {
|
||||||
if (this.className == '_User') {
|
if (this.className == '_User') {
|
||||||
for (var result of results) {
|
for (var result of results) {
|
||||||
delete result.password;
|
delete result.password;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateParseFiles(this.config, results);
|
this.config.filesController.expandFilesInObject(this.config, results);
|
||||||
|
|
||||||
if (this.keys) {
|
if (this.keys) {
|
||||||
var keySet = this.keys;
|
var keySet = this.keys;
|
||||||
results = results.map((object) => {
|
results = results.map((object) => {
|
||||||
var newObject = {};
|
var newObject = {};
|
||||||
for (var key in object) {
|
for (var key in object) {
|
||||||
if (keySet.has(key)) {
|
if (keySet.has(key)) {
|
||||||
newObject[key] = object[key];
|
newObject[key] = object[key];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return newObject;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.redirectClassName) {
|
|
||||||
for (var r of results) {
|
|
||||||
r.className = this.redirectClassName;
|
|
||||||
}
|
}
|
||||||
}
|
return newObject;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.response = {results: results};
|
if (this.redirectClassName) {
|
||||||
});
|
for (var r of results) {
|
||||||
|
r.className = this.redirectClassName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.response = {results: results};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns a promise for whether it was successful.
|
// Returns a promise for whether it was successful.
|
||||||
@@ -497,35 +499,6 @@ function replacePointers(object, path, replace) {
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find file references in REST-format object and adds the url key
|
|
||||||
// with the current mount point and app id
|
|
||||||
// Object may be a single object or list of REST-format objects
|
|
||||||
function updateParseFiles(config, object) {
|
|
||||||
if (object instanceof Array) {
|
|
||||||
object.map((obj) => updateParseFiles(config, obj));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof object !== 'object') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (var key in object) {
|
|
||||||
if (object[key] && object[key]['__type'] &&
|
|
||||||
object[key]['__type'] == 'File') {
|
|
||||||
var filename = object[key]['name'];
|
|
||||||
var encoded = encodeURIComponent(filename);
|
|
||||||
encoded = encoded.replace('%40', '@');
|
|
||||||
if (filename.indexOf('tfss-') === 0) {
|
|
||||||
object[key]['url'] = 'http://files.parsetfss.com/' +
|
|
||||||
config.fileKey + '/' + encoded;
|
|
||||||
} else {
|
|
||||||
object[key]['url'] = config.mount + '/files/' +
|
|
||||||
config.applicationId + '/' +
|
|
||||||
encoded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finds a subobject that has the given key, if there is one.
|
// Finds a subobject that has the given key, if there is one.
|
||||||
// Returns undefined otherwise.
|
// Returns undefined otherwise.
|
||||||
function findObjectWithKey(root, key) {
|
function findObjectWithKey(root, key) {
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ function ParseServer(args) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let filesController = new FilesController(filesAdapter);
|
||||||
|
|
||||||
cache.apps[args.appId] = {
|
cache.apps[args.appId] = {
|
||||||
masterKey: args.masterKey,
|
masterKey: args.masterKey,
|
||||||
collectionPrefix: args.collectionPrefix || '',
|
collectionPrefix: args.collectionPrefix || '',
|
||||||
@@ -74,7 +76,8 @@ function ParseServer(args) {
|
|||||||
dotNetKey: args.dotNetKey || '',
|
dotNetKey: args.dotNetKey || '',
|
||||||
restAPIKey: args.restAPIKey || '',
|
restAPIKey: args.restAPIKey || '',
|
||||||
fileKey: args.fileKey || 'invalid-file-key',
|
fileKey: args.fileKey || 'invalid-file-key',
|
||||||
facebookAppIds: args.facebookAppIds || []
|
facebookAppIds: args.facebookAppIds || [],
|
||||||
|
filesController: filesController
|
||||||
};
|
};
|
||||||
|
|
||||||
// To maintain compatibility. TODO: Remove in v2.1
|
// To maintain compatibility. TODO: Remove in v2.1
|
||||||
@@ -93,7 +96,6 @@ function ParseServer(args) {
|
|||||||
var api = express();
|
var api = express();
|
||||||
|
|
||||||
// File handling needs to be before default middlewares are applied
|
// File handling needs to be before default middlewares are applied
|
||||||
let filesController = new FilesController(filesAdapter);
|
|
||||||
api.use('/', filesController.getExpressRouter());
|
api.use('/', filesController.getExpressRouter());
|
||||||
|
|
||||||
// TODO: separate this from the regular ParseServer object
|
// TODO: separate this from the regular ParseServer object
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ function handleLogIn(req) {
|
|||||||
user.sessionToken = token;
|
user.sessionToken = token;
|
||||||
delete user.password;
|
delete user.password;
|
||||||
|
|
||||||
|
req.config.filesController.expandFilesInObject(req.config, user);
|
||||||
|
|
||||||
var expiresAt = new Date();
|
var expiresAt = new Date();
|
||||||
expiresAt.setFullYear(expiresAt.getFullYear() + 1);
|
expiresAt.setFullYear(expiresAt.getFullYear() + 1);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user