Skip to content
This repository has been archived by the owner on Apr 16, 2024. It is now read-only.

Commit

Permalink
Merge branch 'develop' into feature/#624-update-main-contributors
Browse files Browse the repository at this point in the history
  • Loading branch information
HPunktOchs authored Apr 16, 2018
2 parents def954a + 88bf20a commit 15e0f34
Show file tree
Hide file tree
Showing 22 changed files with 6,697 additions and 3,602 deletions.
2 changes: 1 addition & 1 deletion .docker/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:8.9.0
FROM node:8.11.1

WORKDIR /usr/src/app

Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ script:
- npm run e2e # run end-to-end-tests
- sed -i 's/$TRAVIS_COMMIT/'$TRAVIS_COMMIT'/' src/app/shared/services/raven-error-handler.service.ts
- cd ../..
- .travis/build-fe.sh # build in prod mode
- travis_wait 30 .travis/build-fe.sh # build in prod mode

after_script:
# send required files to coveralls.io
Expand Down
2 changes: 1 addition & 1 deletion api/fixtures/FixtureLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class FixtureLoader {
(<any>mongoose).Promise = global.Promise;

if (!mongoose.connection.readyState) {
mongoose.connect(config.database, {useMongoClient: true});
mongoose.connect(config.database);
}
}

Expand Down
2,768 changes: 1,778 additions & 990 deletions api/package-lock.json

Large diffs are not rendered by default.

82 changes: 41 additions & 41 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,71 +32,71 @@
},
"dependencies": {
"app-root-path": "^2.0.1",
"archiver": "^2.1.0",
"archiver": "^2.1.1",
"bcrypt": "^1.0.3",
"body-parser": "^1.18.2",
"express": "^4.16.2",
"express": "^4.16.3",
"fast-csv": "^2.4.1",
"fs-extra": "^4.0.3",
"jsonwebtoken": "^8.1.0",
"fs-extra": "^5.0.0",
"jsonwebtoken": "^8.2.1",
"migrate-mongoose": "^3.2.2",
"moment": "^2.19.3",
"mongoose": "^4.13.6",
"moment": "^2.22.0",
"mongoose": "^5.0.14",
"morgan": "^1.9.0",
"multer": "^1.3.0",
"node-file-cache": "^1.0.2",
"nodemailer": "^4.4.1",
"nodemailer": "^4.6.4",
"nodemailer-markdown": "^1.0.2",
"passport": "^0.4.0",
"passport-jwt": "^3.0.1",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"raven": "^2.2.1",
"reflect-metadata": "^0.1.10",
"routing-controllers": "^0.7.6",
"raven": "^2.5.0",
"reflect-metadata": "^0.1.12",
"routing-controllers": "^0.7.7",
"stream-buffers": "^3.0.1",
"to-utf-8": "^1.3.0",
"validator": "^9.1.2",
"winston": "^2.4.0"
"validator": "^9.4.1",
"winston": "^2.4.1"
},
"devDependencies": {
"@types/bcrypt": "^1.0.0",
"@types/body-parser": "1.16.8",
"@types/chai": "4.0.8",
"@types/chai-http": "3.0.3",
"@types/express": "4.0.39",
"@types/fs-extra": "^4.0.5",
"@types/jsonwebtoken": "^7.2.4",
"@types/mocha": "^2.2.44",
"@types/mongoose": "^4.7.28",
"@types/chai": "4.1.2",
"@types/chai-http": "3.0.4",
"@types/express": "4.11.1",
"@types/fs-extra": "^5.0.2",
"@types/jsonwebtoken": "^7.2.6",
"@types/mocha": "^5.0.0",
"@types/mongoose": "^5.0.9",
"@types/morgan": "1.7.35",
"@types/nodemailer": "^4.3.1",
"@types/passport": "^0.4.1",
"@types/passport-jwt": "^3.0.0",
"@types/passport-local": "^1.0.32",
"@types/raven": "^2.1.2",
"@types/validator": "^6.3.0",
"@types/winston": "2.3.7",
"@types/nodemailer": "^4.6.0",
"@types/passport": "^0.4.4",
"@types/passport-jwt": "^3.0.1",
"@types/passport-local": "^1.0.33",
"@types/raven": "^2.1.6",
"@types/validator": "^9.4.0",
"@types/winston": "^2.3.9",
"chai": "4.1.2",
"chai-http": "^3.0.0",
"chai-http": "^4.0.0",
"coveralls": "^3.0.0",
"gulp": "3.9.1",
"gulp-apidoc": "^0.2.6",
"gulp-istanbul": "1.1.2",
"gulp-mocha": "4.3.1",
"gulp-apidoc": "^0.2.7",
"gulp-istanbul": "1.1.3",
"gulp-mocha": "5.0.0",
"gulp-nodemon": "2.2.1",
"gulp-plumber": "1.1.0",
"gulp-sourcemaps": "2.6.1",
"gulp-tslint": "8.1.2",
"gulp-typedoc": "2.1.1",
"gulp-typescript": "3.2.3",
"gulp-plumber": "1.2.0",
"gulp-sourcemaps": "2.6.4",
"gulp-tslint": "8.1.3",
"gulp-typedoc": "2.2.0",
"gulp-typescript": "4.0.2",
"mocha-lcov-reporter": "^1.3.0",
"remap-istanbul": "0.9.5",
"remap-istanbul": "0.11.0",
"rimraf": "2.6.2",
"run-sequence": "2.2.0",
"run-sequence": "2.2.1",
"temp": "^0.8.3",
"tslint": "5.8.0",
"typedoc": "^0.9.0",
"typescript": "^2.6.2"
"tslint": "5.9.1",
"typedoc": "^0.11.1",
"typescript": "^2.8.1"
},
"engines": {
"node": ">=4.0.0"
Expand Down
2 changes: 1 addition & 1 deletion api/src/migrations/MigrationHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class MigrationHandler {
(<any>mongoose).Promise = global.Promise;

if (!mongoose.connection.readyState) {
this.databaseConnection = mongoose.connect(config.database, {useMongoClient: true});
this.databaseConnection = mongoose.connect(config.database);
}

fs.readdirSync(__dirname + '/scripts').forEach((file: string) => {
Expand Down
17 changes: 12 additions & 5 deletions api/src/models/Course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {InternalServerError} from 'routing-controllers';
import {IUser} from '../../../shared/models/IUser';
import * as winston from 'winston';
import {ObjectID} from 'bson';
import {Directory} from './mediaManager/Directory';
import {IProperties} from '../../../shared/models/IProperties';
import Pick from '../utilities/Pick';

Expand Down Expand Up @@ -94,11 +95,17 @@ const courseSchema = new mongoose.Schema({
);

// Cascade delete
courseSchema.pre('remove', function (next: () => void) {
Lecture.find({'_id': {$in: this.lectures}}).exec()
.then((lectures) => Promise.all(lectures.map(lecture => lecture.remove())))
.then(next)
.catch(next);
courseSchema.pre('remove', async function (next) {
const localCourse = <ICourseModel><any>this;
try {
const deletedLectures = await Lecture.deleteMany({'_id': {$in: localCourse.lectures}}).exec();
const deletedDirs = await Directory.deleteMany({'_id': {$in: localCourse.media}}).exec();
} catch (error) {
const debug = 0;
next();
}

next();
});

courseSchema.methods.exportJSON = async function (sanitize: boolean = true) {
Expand Down
3 changes: 2 additions & 1 deletion api/src/models/Lecture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ const lectureSchema = new mongoose.Schema({
lectureSchema.pre('remove', function(next: () => void) {
// We cannot do this, because we need actual Unit instances so that their pre remove middleware gets called
// Unit.remove({'_id': {$in: this.units}}).exec().then(next).catch(next);
Unit.find({'_id': {$in: this.units}}).exec()
const localLecture = <ILectureModel><any>this;
Unit.find({'_id': {$in: localLecture.units}}).exec()
.then((units) => Promise.all(units.map(unit => unit.remove())))
.then(next)
.catch(next);
Expand Down
5 changes: 3 additions & 2 deletions api/src/models/mediaManager/Directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,16 @@ const directorySchema = new mongoose.Schema({
});

directorySchema.pre('remove', async function(next: () => void) {
for (const subdir of this.subDirectories) {
const localDir = <IDirectoryModel><any>this;
for (const subdir of localDir.subDirectories) {
// linting won't let us use 'Directory' before it is actually declared
// tslint:disable-next-line:no-use-before-declare
const model = await Directory.findById(subdir);
if (model) {
await model.remove();
}
}
for (const file of this.files) {
for (const file of localDir.files) {
const model = await File.findById(file);
if (model) {
await model.remove();
Expand Down
9 changes: 5 additions & 4 deletions api/src/models/mediaManager/File.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ const fileSchema = new mongoose.Schema({
});

fileSchema.pre('remove', async function(next: () => void) {
if (fs.existsSync(this.physicalPath)) {
await promisify(fs.unlink)(this.physicalPath);
const localFile = <IFileModel><any>this;
if (fs.existsSync(localFile.physicalPath)) {
await promisify(fs.unlink)(localFile.physicalPath);
}

const units2Check: IFileUnitModel[] = <IFileUnitModel[]>await FileUnit.find({files: { $in: [ this._id ] }});
const units2Check: IFileUnitModel[] = <IFileUnitModel[]>await FileUnit.find({files: { $in: [ localFile._id ] }});
Promise.all(units2Check.map(async unit => {
const index = unit.files.indexOf(this._id);
const index = unit.files.indexOf(localFile._id);
if (index > -1) {
unit.files.splice(index, 1);
await unit.save();
Expand Down
12 changes: 7 additions & 5 deletions api/src/models/progress/TaskUnitProgress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@ const taskUnitProgressSchema = new mongoose.Schema({
);

taskUnitProgressSchema.pre('save', async function (next: () => void) {
const taskUnit = <ITaskUnitModel> await Unit.findById(this.unit);
const localProg = <ITaskUnitProgressModel><any>this;
const taskUnit = <ITaskUnitModel> await Unit.findById(localProg.unit);

this.done = true;
localProg.done = true;

taskUnit.tasks.forEach(question => {
question.answers.forEach(answer => {
if (
!this.answers[question._id.toString()] ||
this.answers[question._id.toString()][answer._id.toString()] !== !!answer.value // !! is necessary, because value can be undefined
// !! is necessary, because value can be undefined
!localProg.answers[question._id.toString()] ||
localProg.answers[question._id.toString()][answer._id.toString()] !== !!answer.value
) {
this.done = false;
localProg.done = false;
}
})
});
Expand Down
4 changes: 3 additions & 1 deletion api/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export class Server {
// Do not use mpromise
(<any>mongoose).Promise = global.Promise;

// mongoose.set('debug', true);

this.app = createExpressServer({
routePrefix: '/api',
controllers: [__dirname + '/controllers/*.js'], // register all controller's routes
Expand All @@ -60,7 +62,7 @@ export class Server {
}

start() {
mongoose.connect(config.database, {useMongoClient: true});
mongoose.connect(config.database);

// Request logger
this.app.use(morgan('combined'));
Expand Down
72 changes: 42 additions & 30 deletions api/test/integration/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,35 @@ describe('Auth', () => {
res.body.message.should.be.equal(errorCodes.errorCodes.duplicateUid.code);
});

it('should pass', async () => {
const registerUser = { uid: '5468907',
firstName: 'firstName',
lastName: 'lastName',
role: 'student',
password: 'test1234',
email: '[email protected]'};

const res = await chai.request(app)
.post(`${BASE_URL}/register`)
.send(registerUser)
.catch(err => err.response);

res.status.should.be.equal(204);
});


it('should pass and enroll into course', async () => {
const registerUser: IUser = new User();
registerUser.uid = '5468907';
registerUser.profile.firstName = 'firstName';
registerUser.profile.lastName = 'lastName';
registerUser.role = 'student';
registerUser.password = 'test1234';
registerUser.email = '[email protected]';
const registerUser = { uid: '5468907',
firstName: 'firstName',
lastName: 'lastName',
role: 'student',
password: 'test1234',
email: '[email protected]'};

const whitelistUser = await WhitelistUser.create({
uid: registerUser.uid,
firstName: registerUser.profile.firstName,
lastName: registerUser.profile.lastName
firstName: registerUser.firstName,
lastName: registerUser.lastName
});
const noElemCourse = await Course.create({
name: 'Test Course 1',
Expand All @@ -75,29 +92,24 @@ describe('Auth', () => {
enrollType: 'whitelist',
whitelist: [whitelistUser]
});
return new Promise((resolve, reject) => {
chai.request(app)
const res = await chai.request(app)
.post(`${BASE_URL}/register`)
.send(registerUser)
.end(async (err, res) => {
res.status.should.be.equal(204);
// Get updated Course.
const resultNoElemCourse = await Course.findById(noElemCourse._id)
.populate('whitelist')
.populate('students');
const resultElemCourse = await Course.findById(elemCourse._id)
.populate('whitelist')
.populate('students');
resultNoElemCourse.whitelist.length.should.be.equal(0);
resultNoElemCourse.students.length.should.be.equal(0);
resultElemCourse.whitelist.length.should.be.equal(1);
resultElemCourse.students.length.should.be.equal(1);
resultElemCourse.whitelist[0].uid.should.be.equal(resultElemCourse.students[0].uid);
resultElemCourse.whitelist[0].firstName.should.be.equal(resultElemCourse.students[0].profile.firstName.toLowerCase());
resultElemCourse.whitelist[0].lastName.should.be.equal(resultElemCourse.students[0].profile.lastName.toLowerCase());
resolve();
});
});
.catch(err => err.response);

res.status.should.be.equal(204);
// Get updated Course.
const resultNoElemCourse = await Course.findById(noElemCourse._id)
.populate('whitelist')
.populate('students');
const resultElemCourse = await Course.findById(elemCourse._id)
.populate('whitelist')
.populate('students');
resultNoElemCourse.whitelist.length.should.be.equal(0);
resultNoElemCourse.students.length.should.be.equal(0);
resultElemCourse.whitelist.length.should.be.equal(1);
resultElemCourse.students.length.should.be.equal(1);
resultElemCourse.whitelist[0].uid.should.be.equal(resultElemCourse.students[0].uid);
});

it('should fail (registration as admin)', async () => {
Expand Down
16 changes: 0 additions & 16 deletions api/test/integration/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,22 +254,6 @@ describe('User', () => {
res.body.email.should.be.equal('[email protected]');
});

it('should fail with missing password', async () => {
const student = await FixtureUtils.getRandomStudent();
const updatedUser = student;
updatedUser.password = '1234test';

const res = await chai.request(app)
.put(`${BASE_URL}/${student._id}`)
.set('Authorization', `JWT ${JwtUtils.generateToken(student)}`)
.send(updatedUser)
.catch(err => err.response);

res.status.should.be.equal(400);
res.body.name.should.be.equal('BadRequestError');
res.body.message.should.be.equal('Invalid Current Password!');
});

it('should update user data', async () => {
const student = await FixtureUtils.getRandomStudent();
const updatedUser = student;
Expand Down
1 change: 1 addition & 0 deletions api/test/mocha.opts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ build/test/**/*.js
--reporter spec
--require test/mocha.env.js
--timeout 10000
--exit
Loading

0 comments on commit 15e0f34

Please sign in to comment.