Skip to content

Commit d44a058

Browse files
andrewncatarak
authored andcommitted
Public API: Create new project (fixes processing#1095) (processing#1106)
* Converts import script to use public API endpoints The endpoints don't exist yet, but this is a good way to see how the implementation of the data structures differ. * Exposes public API endpoint to fetch user's sketches * Implements public API delete endpoint * Adds helper to create custom ApplicationError classes * Adds create project endpoint that understand API's data structure This transforms the nested tree of file data into a mongoose Project model * Returns '201 Created' to match API spec * Removes 'CustomError' variable assignment as it shows up in test output * transformFiles will return file validation errors * Tests API project controller * Tests toModel() * Creates default files if no root-level .html file is provided * Do not auto-generate a slug if it is provided Fixes a bug where the slug was auto-generated using the sketch name, even if a slug property had been provided. * Validates uniqueness of slugs for projects created by the public API * Adds tests for slug uniqueness * Configures node's Promise implementation for mongoose (fixes warnings) * Moves createProject tests to match controller location * Adds support for code to ApplicationErrors * deleteProject controller tests * getProjectsForUser controller tests - implements tests - update apiKey tests to use new User mocks * Ensure error objects have consistent property names `message` is used as a high-level description of the errors `detail` is optional and has an plain language explanation of the individual errors `errors` is an array of each individual problem from `detail` in a machine-readable format * Assert environment variables are provided at script start * Version public API * Expect "files" property to always be provided * Fixes linting error * Converts import script to use public API endpoints The endpoints don't exist yet, but this is a good way to see how the implementation of the data structures differ. * Exposes public API endpoint to fetch user's sketches * Implements public API delete endpoint * Adds helper to create custom ApplicationError classes * Adds create project endpoint that understand API's data structure This transforms the nested tree of file data into a mongoose Project model * Returns '201 Created' to match API spec * Removes 'CustomError' variable assignment as it shows up in test output * transformFiles will return file validation errors * Tests API project controller * Tests toModel() * Creates default files if no root-level .html file is provided * Do not auto-generate a slug if it is provided Fixes a bug where the slug was auto-generated using the sketch name, even if a slug property had been provided. * Validates uniqueness of slugs for projects created by the public API * Adds tests for slug uniqueness * Configures node's Promise implementation for mongoose (fixes warnings) * Moves createProject tests to match controller location * deleteProject controller tests * Adds support for code to ApplicationErrors * getProjectsForUser controller tests - implements tests - update apiKey tests to use new User mocks * Ensure error objects have consistent property names `message` is used as a high-level description of the errors `detail` is optional and has an plain language explanation of the individual errors `errors` is an array of each individual problem from `detail` in a machine-readable format * Assert environment variables are provided at script start * Version public API * Expect "files" property to always be provided * Fixes linting error * Checks that authenticated user has permission to create under this namespace Previously, the project was always created under the authenticated user's namespace, but this not obvious behaviour.
1 parent 4432323 commit d44a058

24 files changed

+1902
-549
lines changed

jest.setup.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { configure } from 'enzyme'
22
import Adapter from 'enzyme-adapter-react-16'
33
import '@babel/polyfill'
4+
import mongoose from 'mongoose'
5+
6+
mongoose.Promise = global.Promise;
47

58
configure({ adapter: new Adapter() })
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const getObjectKey = jest.mock();
2+
export const deleteObjectsFromS3 = jest.fn();
3+
export const signS3 = jest.fn();
4+
export const copyObjectInS3 = jest.fn();
5+
export const listObjectsInS3ForUser = jest.fn();

server/controllers/__test__/project.controller.test.js

-155
This file was deleted.

server/controllers/project.controller.js

+3-56
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ import archiver from 'archiver';
22
import format from 'date-fns/format';
33
import isUrl from 'is-url';
44
import jsdom, { serializeDocument } from 'jsdom';
5-
import isBefore from 'date-fns/is_before';
65
import isAfter from 'date-fns/is_after';
76
import request from 'request';
87
import slugify from 'slugify';
98
import Project from '../models/project';
109
import User from '../models/user';
1110
import { resolvePathToFile } from '../utils/filePath';
1211
import generateFileSystemSafeName from '../utils/generateFileSystemSafeName';
13-
import { deleteObjectsFromS3, getObjectKey } from './aws.controller';
1412

15-
export { default as createProject } from './project.controller/createProject';
13+
export { default as createProject, apiCreateProject } from './project.controller/createProject';
14+
export { default as deleteProject } from './project.controller/deleteProject';
15+
export { default as getProjectsForUser, apiGetProjectsForUser } from './project.controller/getProjectsForUser';
1616

1717
export function updateProject(req, res) {
1818
Project.findById(req.params.project_id, (findProjectErr, project) => {
@@ -84,37 +84,6 @@ export function getProject(req, res) {
8484
});
8585
}
8686

87-
function deleteFilesFromS3(files) {
88-
deleteObjectsFromS3(files.filter((file) => {
89-
if (file.url) {
90-
if (!process.env.S3_DATE || (
91-
process.env.S3_DATE &&
92-
isBefore(new Date(process.env.S3_DATE), new Date(file.createdAt)))) {
93-
return true;
94-
}
95-
}
96-
return false;
97-
})
98-
.map(file => getObjectKey(file.url)));
99-
}
100-
101-
export function deleteProject(req, res) {
102-
Project.findById(req.params.project_id, (findProjectErr, project) => {
103-
if (!project.user.equals(req.user._id)) {
104-
res.status(403).json({ success: false, message: 'Session does not match owner of project.' });
105-
return;
106-
}
107-
deleteFilesFromS3(project.files);
108-
Project.remove({ _id: req.params.project_id }, (removeProjectError) => {
109-
if (removeProjectError) {
110-
res.status(404).send({ message: 'Project with that id does not exist' });
111-
return;
112-
}
113-
res.json({ success: true });
114-
});
115-
});
116-
}
117-
11887
export function getProjectsForUserId(userId) {
11988
return new Promise((resolve, reject) => {
12089
Project.find({ user: userId })
@@ -157,10 +126,6 @@ export function getProjectAsset(req, res) {
157126
});
158127
}
159128

160-
export function getProjectsForUserName(username) {
161-
162-
}
163-
164129
export function getProjects(req, res) {
165130
if (req.user) {
166131
getProjectsForUserId(req.user._id)
@@ -173,24 +138,6 @@ export function getProjects(req, res) {
173138
}
174139
}
175140

176-
export function getProjectsForUser(req, res) {
177-
if (req.params.username) {
178-
User.findOne({ username: req.params.username }, (err, user) => {
179-
if (!user) {
180-
res.status(404).json({ message: 'User with that username does not exist.' });
181-
return;
182-
}
183-
Project.find({ user: user._id })
184-
.sort('-createdAt')
185-
.select('name files id createdAt updatedAt')
186-
.exec((innerErr, projects) => res.json(projects));
187-
});
188-
} else {
189-
// could just move this to client side
190-
res.json([]);
191-
}
192-
}
193-
194141
export function projectExists(projectId, callback) {
195142
Project.findById(projectId, (err, project) => (
196143
project ? callback(true) : callback(false)

0 commit comments

Comments
 (0)