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 #537 from h-da/develop
Browse files Browse the repository at this point in the history
Release v0.6.0
  • Loading branch information
grosspersky authored Mar 30, 2018
2 parents e2f966a + 9084cea commit a9cf062
Show file tree
Hide file tree
Showing 89 changed files with 2,059 additions and 441 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ nohup.out

# API
/api/uploads/*
!/api/uploads/.gitkeep
!/api/uploads/users
/api/uploads/users/*
!/api/uploads/users/.gitkeep
/api/temp/*
/api/build
Expand Down
8 changes: 3 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# required for chrome to install
dist: trusty
# required for e2e tests to complete succesfully (page crash???)
# required for e2e tests to complete successfully (page crash???)
sudo: required
language: node_js
node_js:
Expand All @@ -28,10 +28,8 @@ branches:
only:
- develop
- master
# This matches tags wit a format of v{MAJOR}.{MINOR}.{FIX} were major minor and fix is supposed to be a number.
# This matches tags wit a format of v{MAJOR}.{MINOR}.{FIX} were major, minor and fix is supposed to be a number.
- /^v(\d+).(\d+).(\d+)$/
# Only for development purposes
# - feature/14-travis-new

cache:
directories:
Expand Down Expand Up @@ -88,10 +86,10 @@ after_script:

after_success:
- .travis/package-checker.sh
- .travis/apidoc.sh
- .travis/docker.sh
- .travis/deploy.sh
- .travis/sentry.sh
- .travis/apidoc.sh

# Configure notification
notifications:
Expand Down
91 changes: 45 additions & 46 deletions api/fixtures/FixtureUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,61 +6,62 @@ import {ICourse} from '../../shared/models/ICourse';
import {ILecture} from '../../shared/models/ILecture';
import {IUnit} from '../../shared/models/units/IUnit';
import {IUser} from '../../shared/models/IUser';
import {IWhitelistUser} from '../../shared/models/IWhitelistUser';
import {ITaskUnit} from '../../shared/models/units/ITaskUnit';
import {ITaskUnitModel} from '../src/models/units/TaskUnit';
import * as mongoose from 'mongoose';
import ObjectId = mongoose.Types.ObjectId;
import {IWhitelistUser} from '../../shared/models/IWhitelistUser';

export class FixtureUtils {
public static async getRandomUser(hash?: string) {
public static async getRandomUser(hash?: string): Promise<IUser> {
const array = await this.getUser();
return this.getRandom(array, hash);
return this.getRandom<IUser>(array, hash);
}

public static async getRandomUsers(min: number, max: number, hash?: string) {
public static async getRandomUsers(min: number, max: number, hash?: string): Promise<IUser[]> {
const array = await this.getUser();
return this.getRandomArray(array, min, max, hash);
return this.getRandomArray<IUser>(array, min, max, hash);
}

public static async getRandomAdmin(hash?: string) {
public static async getRandomAdmin(hash?: string): Promise<IUser> {
const array = await this.getAdmins();
return this.getRandom(array, hash);
return this.getRandom<IUser>(array, hash);
}

public static async getRandomAdmins(min: number, max: number, hash?: string) {
public static async getRandomAdmins(min: number, max: number, hash?: string): Promise<IUser[]> {
const array = await this.getAdmins();
return this.getRandomArray(array, min, max, hash);
return this.getRandomArray<IUser>(array, min, max, hash);
}

public static async getRandomTeacher(hash?: string) {
public static async getRandomTeacher(hash?: string): Promise<IUser> {
const array = await this.getTeacher();
return this.getRandom(array, hash);
return this.getRandom<IUser>(array, hash);
}

public static async getRandomTeacherForCourse(course: ICourse, hash?: string) {
public static async getRandomTeacherForCourse(course: ICourse, hash?: string): Promise<IUser> {
let array: IUser[] = [];
array = array.concat(course.teachers);
array.push(course.courseAdmin);
const user = await this.getRandom(array, hash);
const user = await this.getRandom<IUser>(array, hash);
return User.findById(user);
}

public static async getRandomTeachers(min: number, max: number, hash?: string) {
public static async getRandomTeachers(min: number, max: number, hash?: string): Promise<IUser[]> {
const array = await this.getTeacher();
return this.getRandomArray(array, min, max, hash);
return this.getRandomArray<IUser>(array, min, max, hash);
}

public static async getRandomStudent(hash?: string) {
public static async getRandomStudent(hash?: string): Promise<IUser> {
const array = await this.getStudents();
return this.getRandom(array, hash);
return this.getRandom<IUser>(array, hash);
}

public static async getRandomStudents(min: number, max: number, hash?: string) {
public static async getRandomStudents(min: number, max: number, hash?: string): Promise<IUser[]> {
const array = await this.getStudents();
return this.getRandomArray(array, min, max, hash);
return this.getRandomArray<IUser>(array, min, max, hash);
}

// FIXME: This should return a valid type. (Promise<IWhitelistUser[]>)
public static async getRandomWhitelistUsers(students: IUser[], course: ICourseModel, hash?: string) {
const randomArray = students.splice(0, this.getRandomNumber(0, students.length - 1));
const array = await this.getRandomArray(randomArray, 0, students.length - 1, hash);
Expand All @@ -74,80 +75,79 @@ export class FixtureUtils {
});
}


public static async getRandomCourse(hash?: string) {
public static async getRandomCourse(hash?: string): Promise<ICourse> {
const array = await this.getCourses();
return this.getRandom(array, hash);
return this.getRandom<ICourse>(array, hash);
}

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

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

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

public static async getRandomLectureFromCourse(course: ICourse, hash?: string) {
const lectureId = await this.getRandom(course.lectures, hash);
public static async getRandomLectureFromCourse(course: ICourse, hash?: string): Promise<ILecture> {
const lectureId = await this.getRandom<ILecture>(course.lectures, hash);
return Lecture.findById(lectureId);
}

public static async getLectureFromUnit(unit: IUnit) {
public static async getLectureFromUnit(unit: IUnit): Promise<ILecture> {
return Lecture.findOne({units: { $in: [ unit._id ] }});
}

public static async getRandomUnit(hash?: string) {
public static async getRandomUnit(hash?: string): Promise<IUnit> {
const array = await this.getUnits();
return this.getRandom(array, hash);
return this.getRandom<IUnit>(array, hash);
}

public static async getRandomUnitFromLecture(lecture: ILecture, hash?: string) {
const unitId = await this.getRandom(lecture.units, hash);
public static async getRandomUnitFromLecture(lecture: ILecture, hash?: string): Promise<IUnit> {
const unitId = await this.getRandom<IUnit>(lecture.units, hash);
return Unit.findById(unitId);
}

public static async getRandomUnitFromCourse(course: ICourse, hash?: string) {
public static async getRandomUnitFromCourse(course: ICourse, hash?: string): Promise<IUnit> {
let units: Array<IUnit> = [];
for (const lecture of course.lectures) {
units = units.concat(lecture.units);
}
const unitId = await this.getRandom(units, hash);
const unitId = await this.getRandom<IUnit>(units, hash);
return Unit.findById(unitId);
}

private static async getAdmins() {
private static async getAdmins(): Promise<IUser[]> {
return this.getUser('admin');
}

private static async getTeacher() {
private static async getTeacher(): Promise<IUser[]> {
return this.getUser('teacher');
}

private static async getStudents() {
private static async getStudents(): Promise<IUser[]> {
return this.getUser('student');
}

public static async getCourses() {
public static async getCourses(): Promise<ICourse[]> {
return Course.find()
.populate('students')
.populate('whitelist');
}

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

public static async getUnits() {
public static async getUnits(): Promise<IUnit[]> {
return Unit.find();
}

private static async getUser(role?: string) {
private static async getUser(role?: string): Promise<IUser[]> {
if (!role) {
return User.find();
}
Expand All @@ -156,7 +156,7 @@ export class FixtureUtils {

// returns a random entry out of the array
// returns always the same entry when you provide the same hash (given the fixture base did not change)
private static async getRandom(array: any[], hash?: string) {
private static async getRandom<T>(array: T[], hash?: string): Promise<T> {
if (hash) {
return array[this.getNumberFromString(hash, 0, array.length)];
} else {
Expand All @@ -166,7 +166,7 @@ export class FixtureUtils {

// returns an random subarray
// returns always the same array when you provide the same hash (given the fixture base did not change)
private static async getRandomArray(array: any[], min: number, max: number, hash?: string) {
private static async getRandomArray<T>(array: T[], min: number, max: number, hash?: string): Promise<T[]> {
if (hash) {
const count = this.getNumberFromString(hash, min, max);
const start = this.getNumberFromString(hash, 0, array.length - count);
Expand All @@ -193,7 +193,7 @@ export class FixtureUtils {
return start + (hash % (end - start));
}

private static shuffleArray (array: Array<any>) {
private static shuffleArray<T>(array: Array<T>): T[] {
let tmp;
let current;
let top = array.length;
Expand All @@ -206,7 +206,6 @@ export class FixtureUtils {
array[top] = tmp;
}
}

return array;
}

Expand Down
4 changes: 2 additions & 2 deletions api/gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ gulp.task(LOAD_FIXTURES, [BUILD_DEV], function () {
});

gulp.task(MIGRATE, [BUILD], function () {
require(__dirname + "/build/migrations/migrate");
require(__dirname + "/build/src/migrations");
});

gulp.task(DEBUG, [BUILD_DEV], function () {
Expand All @@ -251,7 +251,7 @@ gulp.task(INSPECT, [BUILD_DEV], function () {
gulp.task(INSPECT_MIGRATOR, [BUILD_DEV], function () {
return nodemon({
ext: "ts js json",
script: "build/migrations/migrate.js",
script: "build/src/migrate.js",
watch: ["migrations/*"],
tasks: [BUILD_DEV],
nodeArgs: ["--inspect=0.0.0.0:9229"]
Expand Down
2 changes: 1 addition & 1 deletion api/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "geli-api",
"version": "0.5.0",
"version": "0.6.0",
"license": "GPL-3.0",
"repository": "h-da/geli",
"description": "This is the API-Package.json for geli.",
Expand Down
1 change: 1 addition & 0 deletions api/src/config/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ export default {
maxFileSize: 51200,
maxZipSize: 204800,

uploadFolder: process.env.UPLOADFOLDER || (appRoot + '/uploads/'),
};
37 changes: 20 additions & 17 deletions api/src/controllers/CourseController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Authorized, BadRequestError,
Body,
CurrentUser, Delete, ForbiddenError,
Get, HttpError,
Get,
JsonController, NotFoundError,
Param,
Post,
Expand All @@ -21,11 +21,11 @@ import {ObsCsvController} from './ObsCsvController';
import {Course, ICourseModel} from '../models/Course';
import {User} from '../models/User';
import {WhitelistUser} from '../models/WhitelistUser';
import {ICodeKataUnit} from '../../../shared/models/units/ICodeKataUnit';
import emailService from '../services/EmailService';

const multer = require('multer');
import crypto = require('crypto');
import {IUnitModel} from '../models/units/Unit';
import {API_NOTIFICATION_TYPE_ALL_CHANGES, API_NOTIFICATION_TYPE_NONE, NotificationSettings} from '../models/NotificationSettings';
import {Notification} from '../models/Notification';
import * as mongoose from 'mongoose';
Expand Down Expand Up @@ -201,8 +201,8 @@ export class CourseController {
* @apiError NotFoundError
*/
@Get('/:id')
getCourse(@Param('id') id: string, @CurrentUser() currentUser: IUser) {
return Course.findOne({
async getCourse(@Param('id') id: string, @CurrentUser() currentUser: IUser) {
const course = await Course.findOne({
...this.userReadConditions(currentUser),
_id: id
})
Expand All @@ -218,24 +218,27 @@ export class CourseController {
}
}
})
.populate('media')
.populate('courseAdmin')
.populate('teachers')
.populate('students')
.populate('whitelist')
.then((course) => {
if (!course) {
throw new NotFoundError();
}
.exec();

course.lectures.forEach((lecture) => {
lecture.units.forEach((unit) => {
if (unit.__t === 'code-kata' && currentUser.role === 'student') {
(<ICodeKataUnit>unit).code = null;
}
});
});
return course.toObject({virtuals: true});
});
if (!course) {
throw new NotFoundError();
}

course.lectures = await Promise.all(course.lectures.map(async (lecture) => {
lecture.units = await Promise.all(lecture.units.map(async (unit: IUnitModel) => {
unit = await unit.populateUnit();
return unit.secureData(currentUser);
}));

return lecture;
}));

return course.toObject();
}

private userReadConditions(currentUser: IUser) {
Expand Down
Loading

0 comments on commit a9cf062

Please sign in to comment.