Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 17 additions & 15 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@
"plugins": ["@typescript-eslint", "import"],
"extends": ["airbnb"],

"ignorePatterns": [
"node_modules",
"dist",
"packages/api/types.ts"
],
"ignorePatterns": ["node_modules", "dist", "packages/api/types.ts"],

"env":{
"env": {
"browser": true,
"node": true,
"jasmine": true
Expand All @@ -34,11 +30,14 @@
"import/no-extraneous-dependencies": 0,
"import/extensions": 0,
"import-name": 0,
"no-unused-vars": ["error", {
"argsIgnorePattern": "^_",
"args": "after-used",
"ignoreRestSiblings": true
}],
"no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"args": "after-used",
"ignoreRestSiblings": true
}
],

"@typescript-eslint/no-unused-vars": ["error"],
"no-unused-expressions": "off",
Expand All @@ -56,10 +55,13 @@
"jsx-a11y/no-static-element-interactions": 0,
"linebreak-style": 0,
"max-classes-per-file": 0, // Leads to too many files
"no-empty-function": ["error", {"allow": ["constructors"]}], // Needed by NestJS dep injection
"no-empty": [2, {
"allowEmptyCatch": true
}],
"no-empty-function": ["error", { "allow": ["constructors"] }], // Needed by NestJS dep injection
"no-empty": [
2,
{
"allowEmptyCatch": true
}
],
"no-underscore-dangle": 0,
"no-useless-constructor": 0, // Needed by NestJS dep injection
"object-curly-newline": 0,
Expand Down
6 changes: 3 additions & 3 deletions packages/api/src/App.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import path from 'path';

import { AssignmentFileModule } from './AssignmentFile';
import { AssignmentModule } from './Assignment';
import { AssignmentFileModule } from './AssignmentFile';
import { AuthModule } from './Auth';
import { CharacterModule } from './Character';
import { CMSModule } from './CMS';
Expand All @@ -16,10 +15,11 @@ import { PathModule } from './Path';
import { PathUserModule } from './PathUser';
import { QuestionModule } from './Question';
import { StorySectionModule } from './StorySection';
import { UserConceptModule } from './UserConcepts';
import { UserModule } from './User';
import { UserConceptModule } from './UserConcepts';
import { UserModuleModule } from './UserModule';


/**
* Export these dependencies so they can be used in testing
*/
Expand Down
7 changes: 4 additions & 3 deletions packages/api/src/Auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ import { AuthService } from './Auth.service';
import { JWTStrategy } from './strategies/jwt.strategy';
import { LocalStrategy } from './strategies/local.strategy';


@Module({
imports: [
UserModule,
PassportModule,
PassportModule.register({
defaultStrategy: 'jwt'
}),
JwtModule.register({
secret: config.get('auth.jwtSecret'),
signOptions: { expiresIn: '1h' }
})
],
providers: [AuthResolver, AuthService, LocalStrategy, JWTStrategy],
exports: [AuthService]
exports: [AuthService, PassportModule]
})
export class AuthModule {}
12 changes: 6 additions & 6 deletions packages/api/src/Character/Character.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { UseGuards } from '@nestjs/common';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';

import { GQLAuthGuard } from '../Auth/GQLAuth.guard';

import { CharacterService } from './Character.service';
import { Roles } from '../Role/Role.guard';
import { Character, CreateCharacterInput, UpdateCharacterInput } from './Character.entity';
import { CharacterService } from './Character.service';


@Resolver('Character')
export class CharacterResolver {
Expand All @@ -16,19 +16,19 @@ export class CharacterResolver {
return this.characterService.findAll();
}

@UseGuards(GQLAuthGuard)
@Roles('admin')
@Mutation(() => Character)
createCharacter(@Args('character') character: CreateCharacterInput) {
return this.characterService.create(character);
}

@UseGuards(GQLAuthGuard)
@Roles('admin')
@Mutation(() => Character)
async updateCharacter(@Args('character') character: UpdateCharacterInput) {
return this.characterService.update(character);
}

@UseGuards(GQLAuthGuard)
@Roles('admin')
@Mutation(() => Boolean)
async deleteCharacter(@Args('id') id: string) {
return this.characterService.delete(id);
Expand Down
21 changes: 11 additions & 10 deletions packages/api/src/Concept/Concept.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { Resolver, Query, Args, Mutation, ResolveField, Parent } from '@nestjs/graphql';
import { UseGuards } from '@nestjs/common';

import { ConceptService } from './Concept.service';
import { Concept, CreateConceptInput, UpdateConceptInput } from './Concept.entity';
import { Args, Mutation, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql';
import { GQLAuthGuard } from '../Auth/GQLAuth.guard';
import { CMS } from '../CMS/CMS';
import { LessonModule } from '../Lesson';
import { Roles } from '../Role/Role.guard';
import { CurrentUser } from '../User/CurrentUser.decorator';
import { User } from '../User/User.entity';
import { UserConceptService } from '../UserConcepts/UserConcept.service';
import { UserConcept } from '../UserConcepts/UserConcept.entity';
import { LessonModule } from '../Lesson';
import { CMS } from '../CMS/CMS';
import { UserConceptService } from '../UserConcepts/UserConcept.service';
import { Concept, CreateConceptInput, UpdateConceptInput } from './Concept.entity';
import { ConceptService } from './Concept.service';


@Resolver(Concept)
export class ConceptResolver {
Expand Down Expand Up @@ -37,19 +38,19 @@ export class ConceptResolver {
return this.userConceptService.findByUser(user.id);
}

@UseGuards(GQLAuthGuard)
@Roles('admin')
@Mutation(() => Concept)
createConcept(@Args('concept') concept: CreateConceptInput) {
return this.conceptService.create(concept);
}

@UseGuards(GQLAuthGuard)
@Roles('admin')
@Mutation(() => Concept)
updateConcept(@Args('concept') concept: UpdateConceptInput) {
return this.conceptService.update(concept);
}

@UseGuards(GQLAuthGuard)
@Roles('admin')
@Mutation(() => Boolean)
deleteConcept(@Args('conceptId') conceptId: string) {
return this.conceptService.delete(conceptId);
Expand Down
3 changes: 1 addition & 2 deletions packages/api/src/Database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import { SeederService } from './seeders/Seeders.service';
import { TypeORMModule } from './TypeORM.module';
import { CMS } from '../CMS/CMS';


/**
* Main Database Module, used in App.module and testing
*/
Expand Down Expand Up @@ -69,4 +68,4 @@ import { CMS } from '../CMS/CMS';
],
exports: [DatabaseService, SeederService]
})
export class DatabaseModule { }
export class DatabaseModule {}
111 changes: 62 additions & 49 deletions packages/api/src/Database/seeders/Seeders.service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Inject, Injectable } from '@nestjs/common';
import Listr from 'listr';
import { Connection, Repository } from 'typeorm';

import { Assignment } from '../../Assignment/Assignment.entity';
import { AssignmentService } from '../../Assignment/Assignment.service';
import { AssignmentFileService } from '../../AssignmentFile/AssignmentFile.service';
import { Character } from '../../Character/Character.entity';
import { CharacterService } from '../../Character/Character.service';
import { CMS } from '../../CMS/CMS';
import { ConceptService } from '../../Concept/Concept.service';
import { FriendStatus } from '../../Friend/Friend.entity';
import { FriendService } from '../../Friend/Friend.service';
Expand All @@ -19,7 +19,7 @@ import { UserService } from '../../User/User.service';
import { UserPreferencesService } from '../../UserPreferences/UserPreferences.service';
import { DatabaseService } from '../Database.service';
import * as random from './random';
import { CMS } from '../../CMS/CMS';
// import { RoleType } from '../../Role/RoleType.enum';


interface CTX {
Expand All @@ -32,7 +32,6 @@ interface CTX {

@Injectable()
export class SeederService {

/**
* Initializes the database service
* @param connection The connection, which gets injected
Expand All @@ -49,7 +48,7 @@ export class SeederService {
public conceptService: ConceptService,
public friendService: FriendService,
public characterService: CharacterService
) { }
) {}

db = new DatabaseService(this.connection);

Expand All @@ -66,71 +65,85 @@ export class SeederService {
* @param num Number of users you want to create
*/
async seedUsers(num: number = 4): Promise<UserWithPassword[]> {
return Promise.all(Array(num).fill(undefined).map(async (_, i) => {
const user = await this.userService.create(
random.userInput({ email: `user${i}@test.com` })
);

if (i % 2 === 0) {
await this.userPreferencesService.update(
user.id,
random.userPreferenceInput()
);
}
return user;
}));
return Promise.all(
Array(num)
.fill(undefined)
.map(async (_, i) => {
const input = random.userInput({ email: `user${i}@test.com` });
if (i === 0) {
input.email = 'admin@test.com';
// (input as UserWithPassword).role = RoleType.admin;
}
const user = await this.userService.create(input);

if (i % 2 === 0) {
await this.userPreferencesService.update(
user.id,
random.userPreferenceInput()
);
}
return user;
})
);
}

async seedCharacters(num: number = 3): Promise<Character[]> {
return Promise.all(Array(num).fill(undefined).map(async () => this.characterService.create(
random.characterInput()
)));
return Promise.all(
Array(num)
.fill(undefined)
.map(async () => this.characterService.create(random.characterInput()))
);
}


async seedPaths(users: UserWithPassword[] = [], characters: Character[] = []) {
async seedPaths(
users: UserWithPassword[] = [],
characters: Character[] = []
) {
const paths = [
{ id: 'js', name: 'Javascript', icon: 'js' },
{ id: 'css', name: 'CSS', icon: 'css' },
{ id: 'html', name: 'HTML', icon: 'html' }
];

return Promise.all(paths.map(async (path, i) => {
let newPath = new Path();
return Promise.all(
paths.map(async (path, i) => {
let newPath = new Path();

if ((i % 2 === 0) && (i < characters.length)) {
newPath = await this.pathService.create(
random.pathInput({ ...path, characterId: characters[i].id })
);
} else {
newPath = await this.pathService.create(
random.pathInput(path)
);
}
if (i === 0 && users.length) {
await this.pathService.addUserToPath(users[0].id, newPath.id);
}
return newPath;
}));
if (i % 2 === 0 && i < characters.length) {
newPath = await this.pathService.create(
random.pathInput({ ...path, characterId: characters[i].id })
);
} else {
newPath = await this.pathService.create(random.pathInput(path));
}
if (i === 0 && users.length) {
await this.pathService.addUserToPath(users[0].id, newPath.id);
}
return newPath;
})
);
}


async seedConcept(
numConcept: number = 3,
numModule: number = 2,
users: UserWithPassword[]
) {
const modules = Object.values(this.cms.modules);
const numMod = (numModule < modules.length) ? numModule : modules.length;
return Promise.all(Array(numConcept).fill(undefined).map(async (_, i) => {
const concept = await this.conceptService.create(
random.conceptInput(modules[i % numMod].id)
);

if (i === 0) {
await this.conceptService.addUserConcept(concept.id, users[0].id);
}
}));
const numMod = numModule < modules.length ? numModule : modules.length;
return Promise.all(
Array(numConcept)
.fill(undefined)
.map(async (_, i) => {
const concept = await this.conceptService.create(
random.conceptInput(modules[i % numMod].id)
);

if (i === 0) {
await this.conceptService.addUserConcept(concept.id, users[0].id);
}
})
);
}

async seedFriend(users: UserWithPassword[]) {
Expand Down
5 changes: 3 additions & 2 deletions packages/api/src/Path/Path.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CurrentUser } from '../User/CurrentUser.decorator';
import { User } from '../User/User.entity';
import { Path, PathInput, UpdatePathInput } from './Path.entity';
import { PathService } from './Path.service';
import { Roles } from '../Role/Role.guard';

@Resolver(() => Path)
export class PathResolver {
Expand Down Expand Up @@ -43,7 +44,7 @@ export class PathResolver {
return this.pathService.findById(id);
}

@UseGuards(GQLAuthGuard)
@Roles('admin')
@Mutation(() => Path)
createPath(@Args('path') path: PathInput) {
return this.pathService.create(path);
Expand All @@ -67,7 +68,7 @@ export class PathResolver {
return Boolean(await this.pathService.addUserToPath(user.id, paths));
}

@UseGuards(GQLAuthGuard)
@Roles('admin')
@Mutation(() => Path)
async updatePath(
@Args('path') path: UpdatePathInput
Expand Down
Loading