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

Commit

Permalink
Merge pull request #1088 from geli-lms/develop
Browse files Browse the repository at this point in the history
Release 0.8.4
  • Loading branch information
kesselb authored Dec 20, 2018
2 parents 7fd926c + 9fe2083 commit dfac6cc
Show file tree
Hide file tree
Showing 177 changed files with 10,673 additions and 2,131 deletions.
1 change: 1 addition & 0 deletions .docker/api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ RUN mkdir -p /usr/src/app/tmp
RUN chmod a+rwx /usr/src/app/tmp

COPY api/build/src /usr/src/app/
COPY api/build/styles /usr/src/styles/
COPY api/node_modules /usr/src/app/node_modules
COPY api/nlf-licenses.json /usr/src/app/
COPY api/package.json /usr/src/app/
Expand Down
61 changes: 56 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,64 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [[0.8.4](https://github.com/geli-lms/geli/releases/tag/v0.8.4)] - 2018-12-20 - WS 18/19 ❄️-Release
### Added
- Export PDF with styled free text units. [#997](https://github.com/geli-lms/geli/issues/997) [#1047](https://github.com/geli-lms/geli/pull/1047)
- More predefined custom containers. [#996](https://github.com/geli-lms/geli/issues/996)
- Styled code snippets. [#1017](https://github.com/geli-lms/geli/issues/1017)
- `LectureController` success (`200`), access denial (`403`) and not found (`404`) unit tests for all routes. [#1041](https://github.com/geli-lms/geli/issues/1041)
- Various `NotificationController` unit tests (`200`s, `400`s, `403`s, `404`s). [#1065](https://github.com/geli-lms/geli/issues/1065)
- Two `NotificationSettingsController` unit tests for `403` & `404` `PUT` request errors. [#1072](https://github.com/geli-lms/geli/issues/1072)
- `TestHelper` request methods for `PUT` & `DELETE`. [#1041](https://github.com/geli-lms/geli/issues/1041)
- Code kata validation service. [#844](https://github.com/geli-lms/geli/issues/844)
- File ↔ video unit display type switching. [#912](https://github.com/geli-lms/geli/issues/912)

### Fixed
- `bundle.scss` not available in api container. [#1052](https://github.com/geli-lms/geli/issues/1052)

### Changed
- Update `mongoose` to `5.4.x`. [#1003](https://github.com/geli-lms/geli/issues/1003) [#1004](https://github.com/geli-lms/geli/pull/1004) [#1044](https://github.com/geli-lms/geli/pull/1044) [#1077](https://github.com/geli-lms/geli/pull/1077)
- Refactor `LectureController` `GET`/`POST`/`PUT` routes to use `async`/`await`. [#1041](https://github.com/geli-lms/geli/issues/1041)
- Refactor `NotificationController` unit tests in general. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Refactor `NotificationController` to utilize `.orFail` and the `errorCodes` file. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Refactor `ExportController` & `LectureController` to utilize `.orFail`. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Sanitize `{post} /api/lecture/` route parameters by reducing the arbitrary `ILecture` input to `name` & `description`. [#1041](https://github.com/geli-lms/geli/issues/1041)
- Sanitize `NotificationController` `POST` route parameters by taking a `targetType` and `targetId` instead of the separate `changedCourse`/`changedLecture`/`changedUnit` which needed a _(missing)_ consistency check. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Empty success response object in the two `NotificationController` `POST` routes. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Major `NotificationSettingsController` refactoring and changes in general, plus unit test / front-end adjustments. [#1072](https://github.com/geli-lms/geli/issues/1072)
- Disable unit submit button when deadline is over. [#964](https://github.com/geli-lms/geli/issues/964)
- The background image on the index page. [#922](https://github.com/geli-lms/geli/issues/922)

### Removed
- Unused `Notification` class in the front-end. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Unused `NotificationSettings` class in the front-end. [#1072](https://github.com/geli-lms/geli/issues/1072)
- `{post} /api/notificationSettings/` route; functionality now handled completely by `{put} /api/notificationSettings/`. [#1072](https://github.com/geli-lms/geli/issues/1072)

### Fixed
- Some incorrect `FixtureUtils` return types. [#1041](https://github.com/geli-lms/geli/issues/1041) [#1065](https://github.com/geli-lms/geli/issues/1065)
- `LectureController` `404` error handling. [#1041](https://github.com/geli-lms/geli/issues/1041)
- `NotificationController` `404` error handling. [#1065](https://github.com/geli-lms/geli/issues/1065)
- `NotificationSettingsController` `404` `PUT` error handling. [#1072](https://github.com/geli-lms/geli/issues/1072)
- Course list broken when course image in invalid state. [#1053](https://github.com/geli-lms/geli/issues/1053)

### Security
- Fix multiple security issues of the `LectureController`. [#1041](https://github.com/geli-lms/geli/issues/1041)
- Fix missing `teacher` authorization check for the two `NotificationController` `POST` routes. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Fix missing `NotificationController` `POST` `teacher` authorization check. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Fix `{get} /api/notification/` response leaks by introducing `INotificationView`, a reduced and safe variant of the `INotification` interface. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Fix response leaks for all three _(now two)_ `NotificationSettingsController` routes by introducing `INotificationSettingsView`, a strongly reduced _(no own _id)_ and safe variant of the `INotificationSettings` interface. [#1072](https://github.com/geli-lms/geli/issues/1072)
- Secure `{get} /api/notification/` by using the `@CurrentUser` instead of allowing arbitrary id requests. [#1065](https://github.com/geli-lms/geli/issues/1065)
- Secure `{get} /api/notificationSettings/` by using the `@CurrentUser` instead of allowing arbitrary id requests. [#1072](https://github.com/geli-lms/geli/issues/1072)
- Secure `{put} /api/notificationSettings/` by using the `@CurrentUser` instead of allowing arbitrary id requests. [#1072](https://github.com/geli-lms/geli/issues/1072)
- Minimize `NotificationSettingsController` attack surface by severely simplifying its routes. [#1072](https://github.com/geli-lms/geli/issues/1072)

## [[0.8.3](https://github.com/geli-lms/geli/releases/tag/v0.8.3)] - 2018-11-29 - WS 18/19 🚀-Release
### Added
- Chat system access denial unit tests. [#989](https://github.com/geli-lms/geli/issues/989)
- `DuplicationController` access denial unit tests. [#1016](https://github.com/geli-lms/geli/issues/1016)
- `ExportController` access denial unit tests. [#1039](https://github.com/geli-lms/geli/issues/1039)
- `ExportController` 404 unit tests. [#1039](https://github.com/geli-lms/geli/issues/1039)
- `DuplicationController` 404 unit tests. [#1039](https://github.com/geli-lms/geli/issues/1039)
- `DuplicationController` access denial (`403`) unit tests. [#1016](https://github.com/geli-lms/geli/issues/1016)
- `ExportController` access denial (`403`) unit tests. [#1039](https://github.com/geli-lms/geli/issues/1039)
- `ExportController` not found (`404`) unit tests. [#1039](https://github.com/geli-lms/geli/issues/1039)
- `DuplicationController` not found (`404`) unit tests. [#1039](https://github.com/geli-lms/geli/issues/1039)
- `TestHelper` class for shared API unit test functionality. [#989](https://github.com/geli-lms/geli/issues/989) [#1016](https://github.com/geli-lms/geli/issues/1016)
- `extractSingleMongoId` variant of the `ExtractMongoId` utility function(s). [#989](https://github.com/geli-lms/geli/issues/989)
- Show message count for `UnitComponent` chat. [#933](https://github.com/geli-lms/geli/issues/993)
Expand All @@ -44,7 +95,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- EU-DSGVO: Exclusion of comments in the user chat data export. [#998](https://github.com/geli-lms/geli/issues/998)
- Nondeterministic chat system unit test authorization failures. [#989](https://github.com/geli-lms/geli/issues/989)
- Unnecessarily verbose `DuplicationController` route responses. [#1016](https://github.com/geli-lms/geli/issues/1016)
- Prepare `mongoose` update. [#1003](https://github.com/geli-lms/geli/issues/1003) [#1027](https://github.com/geli-lms/geli/pull/1027)
- Prepare `mongoose 5.3.x` update. [#1003](https://github.com/geli-lms/geli/issues/1003) [#1027](https://github.com/geli-lms/geli/pull/1027)
- `ExportController` missing 404 handling. [#1039](https://github.com/geli-lms/geli/issues/1039)
- `DuplicationController` missing 404 handling. [#1039](https://github.com/geli-lms/geli/issues/1039)
- Fix invalid translation key `hasBeenDeleted`. [#1032](https://github.com/geli-lms/geli/pull/1032)
Expand Down
4 changes: 2 additions & 2 deletions api/fixtures/FixtureLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ export class FixtureLoader {

async load() {
if (!mongoose.connection.readyState) {
await mongoose.connect(config.database, {useNewUrlParser: true});
await mongoose.connect(config.database, config.databaseOptions);
}

await mongoose.connection.dropDatabase();
await User.ensureIndexes();
await User.createIndexes();

const userfixtures = fs.readdirSync(this.usersDirectory);
const coursefixtures = fs.readdirSync(this.coursesDirectory);
Expand Down
28 changes: 21 additions & 7 deletions api/fixtures/FixtureUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {User} from '../src/models/User';
import {Course, ICourseModel} from '../src/models/Course';
import {IUserModel} from '../src/models/User';
import {Lecture} from '../src/models/Lecture';
import {Lecture, ILectureModel} from '../src/models/Lecture';
import {Unit, IUnitModel} from '../src/models/units/Unit';
import {ICourse} from '../../shared/models/ICourse';
import {ILecture} from '../../shared/models/ILecture';
Expand Down Expand Up @@ -117,17 +117,17 @@ export class FixtureUtils {
return this.getRandom<ICourse>(coursesWithAllUnitTypes, hash);
}

public static async getCourseFromLecture(lecture: ILecture): Promise<ICourse> {
public static async getCourseFromLecture(lecture: ILecture): Promise<ICourseModel> {
return Course.findOne({lectures: { $in: [ lecture._id ] }});
}

public static async getCourseFromUnit(unit: IUnit): Promise<ICourse> {
public static async getCourseFromUnit(unit: IUnit): Promise<ICourseModel> {
return Course.findById(unit._course);
}

public static async getRandomLecture(hash?: string): Promise<ILecture> {
public static async getRandomLecture(hash?: string): Promise<ILectureModel> {
const array = await this.getLectures();
return this.getRandom<ILecture>(array, hash);
return this.getRandom<ILectureModel>(array, hash);
}

public static async getRandomLectureFromCourse(course: ICourse, hash?: string): Promise<ILecture> {
Expand All @@ -144,7 +144,7 @@ export class FixtureUtils {
return this.getRandom<IUnitModel>(array, hash);
}

public static async getRandomUnitFromLecture(lecture: ILecture, hash?: string): Promise<IUnit> {
public static async getRandomUnitFromLecture(lecture: ILecture, hash?: string): Promise<IUnitModel> {
const unitId = await this.getRandom<IUnit>(lecture.units, hash);
return Unit.findById(unitId);
}
Expand All @@ -167,6 +167,20 @@ export class FixtureUtils {
return {course, roomId};
}

/**
* Obtain an unauthorized teacher for a course.
* This teacher can be used for access denial unit tests.
*
* @param course The teacher can't belong to this given course; i.e. the teacher won't be 'courseAdmin' or one of the 'teachers'.
* @returns A user with 'teacher' role that is not authorized to access the given course.
*/
public static async getUnauthorizedTeacherForCourse(course: ICourse): Promise<IUserModel> {
return await User.findOne({
_id: {$nin: [course.courseAdmin, ...course.teachers]},
role: 'teacher'
});
}

private static async getAdmins(): Promise<IUser[]> {
return this.getUser('admin');
}
Expand All @@ -189,7 +203,7 @@ export class FixtureUtils {
.populate('whitelist');
}

public static async getLectures(): Promise<ILecture[]> {
public static async getLectures(): Promise<ILectureModel[]> {
return Lecture.find();
}

Expand Down
30 changes: 22 additions & 8 deletions api/gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ let mocha = require("gulp-mocha");
let istanbul = require("gulp-istanbul");
let plumber = require("gulp-plumber");
let remapIstanbul = require("remap-istanbul/lib/gulpRemapIstanbul");
let sass = require('gulp-sass');
sass.compiler = require('node-sass');

const CLEAN_BUILD = "clean:build";
const CLEAN_COVERAGE = "clean:coverage";
Expand All @@ -37,6 +39,7 @@ const WATCH_POLL = "watch:poll";
const DEBUG = "debug";
const INSPECT = "inspect";
const INSPECT_MIGRATOR = "migrate:inspect";
const COMPILE_MD_SASS = 'compile:sass:md';

const SRC_GLOB = "./src/**/*";
const TS_SRC_GLOB = SRC_GLOB + ".ts";
Expand All @@ -45,13 +48,17 @@ const TS_TEST_GLOB = TEST_GLOB + ".ts";
const FIXTURES_GLOB = "./fixtures/**/*";
const TS_FIXTURES_GLOB = FIXTURES_GLOB + ".ts";
const TS_MIGRATION_GLOB = "./migrations/**/*.ts";
const MD_SASS_GLOB = "../shared/styles/md/**/*";
const MD_SASS_FILE_SRC = "../shared/styles/md/bundle.scss";


const BUILD_GLOB = "./build/";
const BUILD_TEST_GLOB = BUILD_GLOB + "test/**/*";
const JS_TEST_GLOB = BUILD_TEST_GLOB + ".js";
const BUILD_SRC_GLOB = BUILD_GLOB + "src/**/*";
const JS_SRC_GLOB = BUILD_SRC_GLOB + ".js";
const TS_GLOB = [TS_SRC_GLOB, TS_TEST_GLOB, TS_FIXTURES_GLOB, TS_MIGRATION_GLOB];
const MD_SASS_FILE_DST = BUILD_GLOB + "styles/md";

const tsProject = typescript.createProject("tsconfig.json");

Expand Down Expand Up @@ -110,6 +117,13 @@ gulp.task(COMPILE_TYPESCRIPT, function () {
.pipe(gulp.dest("./build"));
});

// Compiles sass files
gulp.task(COMPILE_MD_SASS, function () {
return gulp.src(MD_SASS_FILE_SRC)
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(MD_SASS_FILE_DST));
});

gulp.task(COPY_FIXTURES, function () {
return gulp.src([FIXTURES_GLOB, "!" + TS_FIXTURES_GLOB], {base: "."})
.pipe(gulp.dest(BUILD_GLOB));
Expand All @@ -122,7 +136,7 @@ gulp.task(BUILD, function (callback) {
});
*/

gulp.task(BUILD, gulp.series(CLEAN_BUILD, TSLINT, COMPILE_TYPESCRIPT, COPY_FIXTURES));
gulp.task(BUILD, gulp.series(CLEAN_BUILD, TSLINT, COMPILE_TYPESCRIPT, COMPILE_MD_SASS, COPY_FIXTURES));

// Runs all required steps for the build in sequence FOR DEVELOP
/*
Expand All @@ -131,7 +145,7 @@ gulp.task(BUILD_DEV, function (callback) {
});
*/

gulp.task(BUILD_DEV, gulp.series(CLEAN_BUILD, TSLINT_DEV, COMPILE_TYPESCRIPT, COPY_FIXTURES));
gulp.task(BUILD_DEV, gulp.series(CLEAN_BUILD, TSLINT_DEV, COMPILE_TYPESCRIPT, COMPILE_MD_SASS, COPY_FIXTURES));

// Generates a documentation based on the code comments in the *.ts files.
gulp.task(GENERATE_DOC, gulp.series(CLEAN_DOC, function () {
Expand All @@ -145,12 +159,12 @@ gulp.task(GENERATE_DOC, gulp.series(CLEAN_DOC, function () {
}));

// Generates an API documentation based on the code comments in the files within ./src/controllers.
gulp.task(GENERATE_API_DOC, gulp.series(CLEAN_API_DOC, function(done){
gulp.task(GENERATE_API_DOC, gulp.series(CLEAN_API_DOC, function (done) {
apidoc({
src: "./src/controllers",
dest: "./apidocs",
config: "."
},done);
}, done);
}));

// Sets up the istanbul coverage
Expand Down Expand Up @@ -215,9 +229,9 @@ gulp.task(TEST_NATIVE, gulp.series(BUILD, CLEAN_COVERAGE));
// Runs the build task and starts the server every time changes are detected.
gulp.task(WATCH, gulp.series(BUILD_DEV, (done) => {
nodemon({
ext: "ts js json",
ext: "ts js json scss",
script: "build/src/server.js",
watch: ["src/*", "test/*"],
watch: ["src/*", "test/*", MD_SASS_GLOB],
tasks: [BUILD_DEV]
});

Expand All @@ -227,9 +241,9 @@ gulp.task(WATCH, gulp.series(BUILD_DEV, (done) => {
// Runs the build task and starts the server every time changes are detected WITH LEGACY-WATCH ENABLED.
gulp.task(WATCH_POLL, gulp.series(BUILD_DEV, (done) => {
nodemon({
ext: "ts js json",
ext: "ts js json scss",
script: "build/src/server.js",
watch: ["src/*", "test/*"],
watch: ["src/*", "test/*", MD_SASS_GLOB],
legacyWatch: true, // Uses the legacy polling to get changes even on docker/vagrant-mounts
tasks: [BUILD_DEV]
});
Expand Down
Loading

0 comments on commit dfac6cc

Please sign in to comment.