Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample create delete api v2 #330

Merged
merged 37 commits into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
07423b9
Add sample create endpoint for api v2
cosa65 Apr 4, 2022
db74fbb
Uncomment pattern rhapsody
cosa65 Apr 4, 2022
e300916
Fix naming of sample technology on sample create
cosa65 Apr 4, 2022
c5eabe7
WIP
cosa65 Apr 5, 2022
d1710e2
Migrate models to classes so that we can pass the sql client we want …
cosa65 Apr 5, 2022
a640e36
Add transactions for createExperiment model calls and createSample as…
cosa65 Apr 5, 2022
70cac5b
Add trx.commit
cosa65 Apr 5, 2022
e9f5eca
Change transaction handling to a more knex-handled approach
cosa65 Apr 6, 2022
b0be3e1
Update sample creation transaction handling too
cosa65 Apr 6, 2022
7c2bdae
Add sample remove api v2
cosa65 Apr 6, 2022
035ccf1
Reenable expressAuthorizationMiddleware for sample#deleteSample
cosa65 Apr 6, 2022
804c1d5
Fix merge conflicts
cosa65 Apr 7, 2022
a50036b
Fix broken renaming
cosa65 Apr 7, 2022
f3d4319
Fix broken renaming
cosa65 Apr 7, 2022
6551325
Capitalize tests
cosa65 Apr 7, 2022
5271c46
Fix tests and add processingconfig back in
cosa65 Apr 7, 2022
36c27aa
Fix some tests
cosa65 Apr 7, 2022
12409be
Fix tests by adding some functionality to support mocking of inherite…
cosa65 Apr 7, 2022
18f5818
Update snapshot
cosa65 Apr 7, 2022
34dff46
Add rename to fix ci
cosa65 Apr 7, 2022
a885400
Fix tests
cosa65 Apr 7, 2022
3202234
Missing rename fix
cosa65 Apr 7, 2022
b259bfa
Add createNewSampleValues for metadata tracks when creating a new sample
cosa65 Apr 8, 2022
05b8180
Rename removeSample to deleteSample and add tests for 2 model/Expeirm…
cosa65 Apr 8, 2022
901c87b
Add test for sampleController
cosa65 Apr 8, 2022
7ab2ffa
Finish tests for model/MetadataTrack
cosa65 Apr 8, 2022
988b731
Add routes tests for sample
cosa65 Apr 8, 2022
3695238
Minor rename
cosa65 Apr 8, 2022
d937abb
Add tests for BasicModel
cosa65 Apr 8, 2022
a061fb1
Cleanup snapshots
cosa65 Apr 8, 2022
699cd6d
Some cleanup and reordering
cosa65 Apr 8, 2022
2c6aee6
Simplify experimentController
cosa65 Apr 8, 2022
9093171
Add erro tests
cosa65 Apr 11, 2022
d367bcd
Add error check for transaction in experiment
cosa65 Apr 11, 2022
6174bbc
Add 403 errors in openapi validation
cosa65 Apr 11, 2022
7eac916
Add transaction check
cosa65 Apr 11, 2022
ca45e9f
Extract table names into tableNames file
cosa65 Apr 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ module.exports = {
"no-console": "off",
// no-return-await disabled because of https://stackoverflow.com/a/44806230
"no-return-await": "off",
"no-multiple-empty-lines": "off",
"no-multiple-empty-lines": "off"
},
};
20 changes: 11 additions & 9 deletions src/api.v2/controllers/experimentController.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
/* eslint-disable import/prefer-default-export */
const _ = require('lodash');

const experiment = require('../model/experiment');
const userAccess = require('../model/userAccess');
const Experiment = require('../model/Experiment');
const UserAccess = require('../model/UserAccess');

const getLogger = require('../../utils/getLogger');
const { OK } = require('../../utils/responses');
const sqlClient = require('../../sql/sqlClient');

const logger = getLogger('[ExperimentController] - ');

const getAllExperiments = async (req, res) => {
const { user: { sub: userId } } = req;

const data = await experiment.getAllExperiments(userId);
const data = await new Experiment().getAllExperiments(userId);

res.json(data);
};
Expand All @@ -22,7 +22,7 @@ const getExperiment = async (req, res) => {

logger.log(`Getting experiment ${experimentId}`);

const data = await experiment.getExperimentData(experimentId);
const data = await new Experiment().getExperimentData(experimentId);

logger.log(`Finished getting experiment ${experimentId}`);

Expand All @@ -36,8 +36,10 @@ const createExperiment = async (req, res) => {

logger.log('Creating experiment');

await experiment.create({ id: experimentId, name, description });
await userAccess.createNewExperimentPermissions(user.sub, experimentId);
await sqlClient.get().transaction(async (trx) => {
await new Experiment(trx).create({ id: experimentId, name, description });
await new UserAccess(trx).createNewExperimentPermissions(user.sub, experimentId);
});

logger.log(`Finished creating experiment ${experimentId}`);

Expand All @@ -51,7 +53,7 @@ const patchExperiment = async (req, res) => {

const snakeCasedKeysToPatch = _.mapKeys(body, (_value, key) => _.snakeCase(key));

await experiment.update(experimentId, snakeCasedKeysToPatch);
await new Experiment().update(experimentId, snakeCasedKeysToPatch);

logger.log(`Finished updating experiment ${experimentId}`);

Expand All @@ -73,7 +75,7 @@ const updateSamplePosition = async (req, res) => {
return;
}

await experiment.updateSamplePosition(experimentId, oldPosition, newPosition);
await new Experiment().updateSamplePosition(experimentId, oldPosition, newPosition);

logger.log(`Finished reordering samples in ${experimentId}`);

Expand Down
55 changes: 55 additions & 0 deletions src/api.v2/controllers/sampleController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const Sample = require('../model/Sample');
const Experiment = require('../model/Experiment');
const MetadataTrack = require('../model/MetadataTrack');

const getLogger = require('../../utils/getLogger');
const { OK } = require('../../utils/responses');

const sqlClient = require('../../sql/sqlClient');

const logger = getLogger('[SampleController] - ');

const createSample = async (req, res) => {
const {
params: { experimentId, sampleId },
body: { name, sampleTechnology },
} = req;

logger.log('Creating sample');

await sqlClient.get().transaction(async (trx) => {
await new Sample(trx).create({
id: sampleId,
experiment_id: experimentId,
name,
sample_technology: sampleTechnology,
});

await new Experiment(trx).addSample(experimentId, sampleId);

await new MetadataTrack(trx)
.createNewSampleValues(experimentId, sampleId);
});

logger.log(`Finished creating sample ${sampleId} for experiment ${experimentId}`);

res.json(OK());
};

const deleteSample = async (req, res) => {
const { params: { experimentId, sampleId } } = req;

await sqlClient.get().transaction(async (trx) => {
await new Sample(trx).destroy(sampleId);
await new Experiment(trx).deleteSample(experimentId, sampleId);
});

logger.log(`Finished deleting sample ${sampleId} from experiment ${experimentId}`);

res.json(OK());
};

module.exports = {
createSample,
deleteSample,
};
66 changes: 0 additions & 66 deletions src/api.v2/helpers/generateBasicModelFunctions.js

This file was deleted.

4 changes: 2 additions & 2 deletions src/api.v2/middlewares/authMiddlewares.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// for how JWT verification works with Cognito.
const { UnauthorizedError, UnauthenticatedError } = require('../../utils/responses');

const userAccess = require('../model/userAccess');
const UserAccess = require('../model/UserAccess');

/**
* General authorization middleware. Resolves with nothing on
Expand All @@ -20,7 +20,7 @@ const userAccess = require('../model/userAccess');
const authorize = async (userId, resource, method, experimentId) => {
// authResource is always experimentId in V2 because there is no project

const granted = await userAccess.canAccessExperiment(
const granted = await new UserAccess().canAccessExperiment(
userId,
experimentId,
resource,
Expand Down
71 changes: 71 additions & 0 deletions src/api.v2/model/BasicModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// The basic functions of a model that uses Knexjs to store and retrieve data from a
// database using the provided `knex` instance. Custom functionality can be
// composed on top of this set of common functions.
//
// The idea is that these are the most-used types of functions that most/all
// "models" will want to have.

class BasicModel {
constructor(sql, tableName, selectableProps = [], timeout = 4000) {
this.sql = sql;
this.tableName = tableName;
this.selectableProps = selectableProps;
this.timeout = timeout;
}

create(props) {
return this.sql.insert(props)
.returning(this.selectableProps)
.into(this.tableName)
.timeout(this.timeout);
}

findAll() {
return this.sql
.select(this.selectableProps)
.from(this.tableName)
.timeout(this.timeout);
}

find(filters) {
return this.sql.select(this.selectableProps)
.from(this.tableName)
.where(filters)
.timeout(this.timeout);
}

// Same as `find` but only returns the first match if >1 are found.
findOne(filters) {
return this.find(filters)
// @ts-ignore
.then((results) => {
if (!Array.isArray(results)) return results;

return results[0];
});
}

findById(id) {
return this.sql.select(this.selectableProps)
.from(this.tableName)
.where({ id })
.timeout(this.timeout);
}

update(id, props) {
return this.sql.update(props)
.from(this.tableName)
.where({ id })
.returning(this.selectableProps)
.timeout(this.timeout);
}

destroy(id) {
return this.sql.del()
.from(this.tableName)
.where({ id })
.timeout(this.timeout);
}
}

module.exports = BasicModel;
Loading