Index: src/Clients/Angular/finki-chattery/src/app/app-routing.module.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/app-routing.module.ts	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/app-routing.module.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -2,4 +2,5 @@
 import { Routes, RouterModule } from '@angular/router';
 import { AuthCallbackComponent } from './auth-callback/auth-callback.component';
+import { AuthorizedModeratorGuard } from './core/guards/authorized-moderator.guard';
 import { AuthorizedGuard } from './core/guards/authorized.guard';
 
@@ -9,4 +10,9 @@
     canActivate: [AuthorizedGuard],
     loadChildren: () => import('./modules/questioning/questioning.module').then((x) => x.QuestioningModule)
+  },
+  {
+    path: 'moderating',
+    canActivate: [AuthorizedGuard, AuthorizedModeratorGuard],
+    loadChildren: () => import('./modules/moderating/moderating.module').then((x) => x.ModeratingModule)
   },
   {
Index: src/Clients/Angular/finki-chattery/src/app/core/guards/authorized-moderator.guard.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/core/guards/authorized-moderator.guard.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/core/guards/authorized-moderator.guard.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,14 @@
+import { Injectable } from '@angular/core';
+import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
+import { AuthService } from '../services';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class AuthorizedModeratorGuard implements CanActivate {
+  constructor(private auth: AuthService) {}
+
+  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+    return this.auth.isModerator();
+  }
+}
Index: src/Clients/Angular/finki-chattery/src/app/core/services/auth.service.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/core/services/auth.service.ts	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/core/services/auth.service.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -64,4 +64,8 @@
   }
 
+  public isModerator(): boolean {
+    return this.user !== null && this.user.userType === ApplicationUserType.Moderator;
+  }
+
   public currentUser(): ApplicationUser | null {
     return this.user;
Index: src/Clients/Angular/finki-chattery/src/app/core/services/redirect.service.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/core/services/redirect.service.ts	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/core/services/redirect.service.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -21,4 +21,7 @@
         case ApplicationUserType.Teacher:
           break;
+        case ApplicationUserType.Moderator:
+          this.router.navigateByUrl(`moderating/categories`);
+          break;
       }
     }
Index: src/Clients/Angular/finki-chattery/src/app/core/state/category-facade.service.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/core/state/category-facade.service.ts	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/core/state/category-facade.service.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -6,5 +6,5 @@
 
 import { CategoryStateViewModel } from 'src/app/shared-app/models';
-import { EffectStartedWorking, GetCategoriesState } from './category-state/category.actions';
+import { AddCategory, EffectStartedWorking, GetCategoriesState } from './category-state/category.actions';
 import { categoriesStateQuery } from './category-state/category.selectors';
 import { CategoryState } from './category-state/category.state';
@@ -17,17 +17,5 @@
 
   constructor(private store: Store<CategoryState>) {
-    this.effectWorking$ = this.store.select(categoriesStateQuery.effectWorking).pipe(
-      filter((effect) => effect !== null),
-      map((effect) => {
-        if (effect instanceof HttpErrorResponse) {
-          throw effect;
-        } else {
-          return effect;
-        }
-      }),
-      catchError((err) => {
-        return throwError(err);
-      })
-    );
+    this.effectWorking$ = this.store.select(categoriesStateQuery.effectWorking).pipe(filter((effect) => effect !== null));
   }
 
@@ -38,4 +26,8 @@
   public fetchCategories(): void {
     this.dispatchEffect(new GetCategoriesState());
+  }
+
+  public addNewCategory(name: string): void {
+    this.dispatchEffect(new AddCategory(name));
   }
 
Index: src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category-state-request.models.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category-state-request.models.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category-state-request.models.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,3 @@
+export class CreateCategoryRequest {
+  constructor(public name: string) {}
+}
Index: src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.actions.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.actions.ts	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.actions.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -2,9 +2,10 @@
 import { Action } from '@ngrx/store';
 import { CategoryStateViewModel } from 'src/app/shared-app/models';
-import { CategoryStateResponse } from './category-state.models';
 
 export enum CategoryActionTypes {
   GetCategoriesState = '[Category] Get state',
   GetCategoriesStateSuccess = '[Category] Get state success',
+  AddCategory = '[Category] AddCategory',
+  AddCategorySuccess = '[Category] AddCategorySuccess success',
   EffectStartedWorking = '[Category] Effect Started Working',
   EffectFinishedWorking = '[Category] Effect Finished Working',
@@ -22,4 +23,16 @@
 
   constructor(public payload: CategoryStateViewModel[]) {}
+}
+
+export class AddCategory implements Action {
+  readonly type = CategoryActionTypes.AddCategory;
+
+  constructor(public name: string) {}
+}
+
+export class AddCategorySuccess implements Action {
+  readonly type = CategoryActionTypes.AddCategorySuccess;
+
+  constructor(public payload: CategoryStateViewModel) {}
 }
 
@@ -42,3 +55,8 @@
 }
 
-export type CategoryAction = GetCategoriesStateSuccess | EffectStartedWorking | EffectFinishedWorking | EffectFinishedWorkingError;
+export type CategoryAction =
+  | GetCategoriesStateSuccess
+  | AddCategorySuccess
+  | EffectStartedWorking
+  | EffectFinishedWorking
+  | EffectFinishedWorkingError;
Index: src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.effects.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.effects.ts	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.effects.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -1,10 +1,13 @@
 import { Injectable } from '@angular/core';
 import { Actions, createEffect, ofType } from '@ngrx/effects';
-import { catchError, switchMap } from 'rxjs/operators';
+import { catchError, mergeMap, switchMap } from 'rxjs/operators';
 import { TranslateFromJsonService } from 'src/app/shared-app/services';
 
 import { BaseApiService } from 'src/app/shared-app/services/base-api.service';
+import { CreateCategoryRequest } from './category-state-request.models';
 import { CategoryStateResponse } from './category-state.models';
 import {
+  AddCategory,
+  AddCategorySuccess,
   CategoryActionTypes,
   EffectFinishedWorking,
@@ -35,3 +38,18 @@
     );
   });
+
+  addCategory$ = createEffect(() => {
+    return this.actions$.pipe(
+      ofType<AddCategory>(CategoryActionTypes.AddCategory),
+      mergeMap((action) => {
+        return this.api.post<string>(`v1/categories`, new CreateCategoryRequest(action.name)).pipe(
+          switchMap((state) => [
+            new AddCategorySuccess(CategoriesMapper.ToCategoryStateViewModel(state, action.name, this.translate)),
+            new EffectFinishedWorking()
+          ]),
+          catchError((err) => [new EffectFinishedWorkingError(err)])
+        );
+      })
+    );
+  });
 }
Index: src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.mapper.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.mapper.ts	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.mapper.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -10,3 +10,7 @@
     return categoriesResponse.map((x) => new CategoryStateViewModel(x.uid, x.name, translate.instant(x.name)));
   }
+
+  public static ToCategoryStateViewModel(uid: string, name: string, translate: TranslateFromJsonService): CategoryStateViewModel {
+    return new CategoryStateViewModel(uid, name, translate.instant(name));
+  }
 }
Index: src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.reducers.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.reducers.ts	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/core/state/category-state/category.reducers.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -9,4 +9,10 @@
         categories: action.payload
       };
+    case CategoryActionTypes.AddCategorySuccess: {
+      return {
+        ...state,
+        categories: [action.payload, ...state.categories]
+      };
+    }
     case CategoryActionTypes.EffectStartedWorking: {
       return {
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/categories-main/categories-main.component.html
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/categories-main/categories-main.component.html	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/categories-main/categories-main.component.html	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,14 @@
+<div class="margin-xl">
+  <h1>Categories</h1>
+  <app-button [buttonType]="ButtonType.CallToAction" (action)="createNewCategory()">Create new category</app-button>
+  <hr />
+  <table mat-table [dataSource]="categories" class="mat-elevation-z8">
+    <ng-container matColumnDef="name">
+      <th mat-header-cell *matHeaderCellDef>Name</th>
+      <td mat-cell *matCellDef="let element">{{ element.translatedName }}</td>
+    </ng-container>
+
+    <tr mat-header-row *matHeaderRowDef="categoriesColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: categoriesColumns"></tr>
+  </table>
+</div>
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/categories-main/categories-main.component.spec.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/categories-main/categories-main.component.spec.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/categories-main/categories-main.component.spec.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CategoriesMainComponent } from './categories-main.component';
+
+describe('CategoriesMainComponent', () => {
+  let component: CategoriesMainComponent;
+  let fixture: ComponentFixture<CategoriesMainComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ CategoriesMainComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(CategoriesMainComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/categories-main/categories-main.component.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/categories-main/categories-main.component.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/categories-main/categories-main.component.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,37 @@
+import { HttpErrorResponse } from '@angular/common/http';
+import { Component, OnInit } from '@angular/core';
+import { map } from 'rxjs/operators';
+import { NotificationService } from 'src/app/core/services/notification.service';
+import { CategoryFacadeService } from 'src/app/core/state/category-facade.service';
+import { ButtonType } from 'src/app/shared-app/components/generic/button/button.models';
+import { ModeratingDialogService } from '../../services/moderating-dialog.service';
+
+@Component({
+  selector: 'app-categories-main',
+  templateUrl: './categories-main.component.html',
+  styleUrls: ['./categories-main.component.scss']
+})
+export class CategoriesMainComponent implements OnInit {
+  public categories = this.categoriesFacade.getCategories().pipe(map((x) => (x !== null ? x : [])));
+  public categoriesColumns: string[] = ['name'];
+  public ButtonType = ButtonType;
+
+  constructor(
+    private categoriesFacade: CategoryFacadeService,
+    private dialog: ModeratingDialogService,
+    private notification: NotificationService
+  ) {}
+
+  ngOnInit(): void {
+    this.categoriesFacade.fetchCategories();
+    this.categoriesFacade.effectWorking$.subscribe((effect) => {
+      if (effect instanceof HttpErrorResponse) {
+        this.notification.handleErrorsNotification(effect.error);
+      }
+    });
+  }
+
+  createNewCategory(): void {
+    this.dialog.createNewCategory();
+  }
+}
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/create-category-dialog/create-category-dialog.component.html
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/create-category-dialog/create-category-dialog.component.html	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/create-category-dialog/create-category-dialog.component.html	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,17 @@
+<h1 mat-dialog-title>{{ 'create-new-category' | translate }}</h1>
+<mat-dialog-content>
+  <form [formGroup]="formGroup">
+    <mat-form-field class="full-width margin-bottom-sm" appearance="fill" appHandleInputFormErrors>
+      <mat-label>{{ 'category-title' | translate }}</mat-label>
+      <input matInput [formControl]="textField" />
+    </mat-form-field>
+  </form>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <app-button class="margin-right-sm" [buttonType]="ButtonType.Basic" (action)="dialogRef.close()">
+    {{ 'close-button' | translate }}
+  </app-button>
+  <app-button [buttonType]="ButtonType.CallToAction" [disabled]="!formGroup.valid" (action)="submit()">
+    {{ 'submit-button' | translate }}
+  </app-button>
+</mat-dialog-actions>
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/create-category-dialog/create-category-dialog.component.spec.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/create-category-dialog/create-category-dialog.component.spec.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/create-category-dialog/create-category-dialog.component.spec.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CreateCategoryDialogComponent } from './create-category-dialog.component';
+
+describe('CreateCategoryDialogComponent', () => {
+  let component: CreateCategoryDialogComponent;
+  let fixture: ComponentFixture<CreateCategoryDialogComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ CreateCategoryDialogComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(CreateCategoryDialogComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/create-category-dialog/create-category-dialog.component.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/create-category-dialog/create-category-dialog.component.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/create-category-dialog/create-category-dialog.component.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,29 @@
+import { Component, OnInit } from '@angular/core';
+import { FormControl, Validators, FormGroup } from '@angular/forms';
+import { MatDialogRef } from '@angular/material/dialog';
+import { CategoryFacadeService } from 'src/app/core/state/category-facade.service';
+import { ButtonType } from 'src/app/shared-app/components/generic/button/button.models';
+
+@Component({
+  selector: 'app-create-category-dialog',
+  templateUrl: './create-category-dialog.component.html',
+  styleUrls: ['./create-category-dialog.component.scss']
+})
+export class CreateCategoryDialogComponent implements OnInit {
+  public ButtonType = ButtonType;
+  public textField = new FormControl('', [Validators.required, Validators.maxLength(500)]);
+  public formGroup: FormGroup;
+
+  constructor(public dialogRef: MatDialogRef<CreateCategoryDialogComponent>, private categoryFacade: CategoryFacadeService) {
+    this.formGroup = new FormGroup({
+      text: this.textField
+    });
+  }
+
+  ngOnInit(): void {}
+
+  submit(): void {
+    this.categoryFacade.addNewCategory(this.textField.value);
+    this.dialogRef.close();
+  }
+}
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/moderating-components.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/moderating-components.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/components/moderating-components.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,4 @@
+import { CategoriesMainComponent } from './categories-main/categories-main.component';
+import { CreateCategoryDialogComponent } from './create-category-dialog/create-category-dialog.component';
+
+export const MODERATING_COMPONENTS: any[] = [CategoriesMainComponent, CreateCategoryDialogComponent];
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/moderating.module.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/moderating.module.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/moderating.module.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,10 @@
+import { NgModule } from '@angular/core';
+import { SharedAppModule } from 'src/app/shared-app/shared-app.module';
+import { MODERATING_COMPONENTS } from './components/moderating-components';
+import { ModeratingRoutingModule } from './moderating.routes';
+
+@NgModule({
+  declarations: [MODERATING_COMPONENTS],
+  imports: [SharedAppModule, ModeratingRoutingModule]
+})
+export class ModeratingModule {}
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/moderating.routes.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/moderating.routes.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/moderating.routes.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,16 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { CategoriesMainComponent } from './components/categories-main/categories-main.component';
+
+const routes: Routes = [
+  {
+    component: CategoriesMainComponent,
+    path: 'categories'
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule]
+})
+export class ModeratingRoutingModule {}
Index: src/Clients/Angular/finki-chattery/src/app/modules/moderating/services/moderating-dialog.service.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/modules/moderating/services/moderating-dialog.service.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/Clients/Angular/finki-chattery/src/app/modules/moderating/services/moderating-dialog.service.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,21 @@
+import { Injectable } from '@angular/core';
+import { MatDialog, MatDialogRef } from '@angular/material/dialog';
+import { Observable } from 'rxjs';
+import { CreateCategoryDialogComponent } from '../components/create-category-dialog/create-category-dialog.component';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class ModeratingDialogService {
+  constructor(private dialog: MatDialog) {}
+
+  public createNewCategory(): Observable<any> {
+    let dialogRef: MatDialogRef<CreateCategoryDialogComponent>;
+    dialogRef = this.dialog.open(CreateCategoryDialogComponent, {
+      width: '650px',
+      height: 'auto'
+    });
+
+    return dialogRef.afterClosed();
+  }
+}
Index: src/Clients/Angular/finki-chattery/src/app/shared-app/components/generic/header/header.component.html
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/shared-app/components/generic/header/header.component.html	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/shared-app/components/generic/header/header.component.html	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -16,5 +16,5 @@
       'header-ask-question' | translate
     }}</app-button>
-    <app-button [matMenuTriggerFor]="menu" class="margin-y-xs" *ngIf="auth.isLoggedIn()" [buttonType]="ButtonType.Basic">{{
+    <app-button [matMenuTriggerFor]="menu" class="margin-y-xs" *ngIf="auth.isStudent()" [buttonType]="ButtonType.Basic">{{
       'header-student-questions' | translate
     }}</app-button>
Index: src/Clients/Angular/finki-chattery/src/app/shared-app/components/generic/header/header.component.ts
===================================================================
--- src/Clients/Angular/finki-chattery/src/app/shared-app/components/generic/header/header.component.ts	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/app/shared-app/components/generic/header/header.component.ts	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -28,4 +28,7 @@
       this.router.navigateByUrl('questioning/preview');
     }
+    if (this.auth.isModerator()) {
+      this.router.navigateByUrl('moderating/categories');
+    }
   }
 
Index: src/Clients/Angular/finki-chattery/src/assets/translations/en.json
===================================================================
--- src/Clients/Angular/finki-chattery/src/assets/translations/en.json	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/Clients/Angular/finki-chattery/src/assets/translations/en.json	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -81,4 +81,7 @@
   "AnswerAlreadyUpvoted": "You have already upvoted this answer",
   "AnswerAlreadyDownvoted": "You have already downvoted this answer",
-  "StudentHasBadReputation": "You have bad reputation and can not vote"
+  "StudentHasBadReputation": "You have bad reputation and can not vote",
+  "CategoryNameAlreadyExists": "Category with that name already exists",
+  "category-title": "Category title",
+  "create-new-category": "Create new category"
 }
Index: src/FinkiChattery/FinkiChattery.Api/ApplicationServices/Authentication/AuthenticationPolicy.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Api/ApplicationServices/Authentication/AuthenticationPolicy.cs	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/FinkiChattery/FinkiChattery.Api/ApplicationServices/Authentication/AuthenticationPolicy.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -4,4 +4,5 @@
     {
         public const string Student = "Student";
+        public const string Moderator = "Moderator";
     }
 }
Index: src/FinkiChattery/FinkiChattery.Api/ApplicationServices/Authentication/Requirements/ModeratorRequirement.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Api/ApplicationServices/Authentication/Requirements/ModeratorRequirement.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/FinkiChattery/FinkiChattery.Api/ApplicationServices/Authentication/Requirements/ModeratorRequirement.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,11 @@
+﻿using FinkiChattery.Common.User;
+
+namespace FinkiChattery.Api.ApplicationServices.Authentication
+{
+    public class ModeratorRequirement : CurrentUserIsOfRoleRequirement
+    {
+        public ModeratorRequirement() : base(UserRole.Moderator)
+        {
+        }
+    }
+}
Index: src/FinkiChattery/FinkiChattery.Api/Controllers/v1/CategoriesController.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Api/Controllers/v1/CategoriesController.cs	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/FinkiChattery/FinkiChattery.Api/Controllers/v1/CategoriesController.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -1,5 +1,9 @@
-﻿using FinkiChattery.Api.ApplicationServices.Questioning;
+﻿using FinkiChattery.Api.ApplicationServices.Authentication;
+using FinkiChattery.Api.ApplicationServices.Questioning;
+using FinkiChattery.Commands.Moderating;
 using FinkiChattery.Common.Mediator.Interfaces;
+using FinkiChattery.Contracts.Moderating;
 using FinkiChattery.Queries.Questioning;
+using IdentityServer4.AccessTokenValidation;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
@@ -27,4 +31,12 @@
             return Ok(categoriesList.ToCategoryDtos());
         }
+
+        [HttpPost]
+        [Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme, Policy = AuthenticationPolicy.Moderator)]
+        public async Task<IActionResult> CreateNewCategory([FromBody] CreateCategoryRequest request)
+        {
+            var categoryUid = await MediatorService.SendAsync(new CreateCategoryCommand(request.Name));
+            return Ok(categoryUid);
+        }
     }
 }
Index: src/FinkiChattery/FinkiChattery.Api/Services/RegisterServices.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Api/Services/RegisterServices.cs	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/FinkiChattery/FinkiChattery.Api/Services/RegisterServices.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -94,4 +94,5 @@
             {
                 options.AddPolicy(AuthenticationPolicy.Student, policy => policy.Requirements.Add(new StudentRequirement()));
+                options.AddPolicy(AuthenticationPolicy.Moderator, policy => policy.Requirements.Add(new ModeratorRequirement()));
 
             });
Index: src/FinkiChattery/FinkiChattery.Commands/Moderating/CreateCategory/CreateCategoryCommand.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Commands/Moderating/CreateCategory/CreateCategoryCommand.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/FinkiChattery/FinkiChattery.Commands/Moderating/CreateCategory/CreateCategoryCommand.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,43 @@
+﻿using FinkiChattery.Common.Mediator.Contracs;
+using FinkiChattery.Persistence.Models;
+using FinkiChattery.Persistence.UnitOfWork;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FinkiChattery.Commands.Moderating
+{
+    public class CreateCategoryCommand : ICommand<Guid>
+    {
+        public CreateCategoryCommand(string categoryName)
+        {
+            CategoryName = categoryName;
+        }
+
+        public string CategoryName { get; }
+    }
+
+    public class CreateCategoryHandler : ICommandHandler<CreateCategoryCommand, Guid>
+    {
+        public CreateCategoryHandler(IUnitOfWork unitOfWork)
+        {
+            UnitOfWork = unitOfWork;
+        }
+
+        public IUnitOfWork UnitOfWork { get; }
+
+        public async Task<Guid> Handle(CreateCategoryCommand request, CancellationToken cancellationToken)
+        {
+            var category = new Category()
+            {
+                Name = request.CategoryName
+            };
+
+            UnitOfWork.Categories.Add(category);
+
+            await UnitOfWork.SaveAsync();
+
+            return category.Uid;
+        }
+    }
+}
Index: src/FinkiChattery/FinkiChattery.Commands/Moderating/CreateCategory/CreateCategoryValidator.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Commands/Moderating/CreateCategory/CreateCategoryValidator.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/FinkiChattery/FinkiChattery.Commands/Moderating/CreateCategory/CreateCategoryValidator.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,17 @@
+﻿using FinkiChattery.Commands.Moderating.Validators;
+using FinkiChattery.Persistence.UnitOfWork;
+using FluentValidation;
+
+namespace FinkiChattery.Commands.Moderating
+{
+    public class CreateCategoryValidator : AbstractValidator<CreateCategoryCommand>
+    {
+        public CreateCategoryValidator(IUnitOfWork unitOfWork)
+        {
+            CascadeMode = CascadeMode.Stop;
+
+            RuleFor(x => x.CategoryName).CategoryTitleValidate();
+            RuleFor(x => x.CategoryName).SetValidator(new CategoryWithNameIsUnique(unitOfWork));
+        }
+    }
+}
Index: src/FinkiChattery/FinkiChattery.Commands/Moderating/ModeratingErrorCodes .cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Commands/Moderating/ModeratingErrorCodes .cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/FinkiChattery/FinkiChattery.Commands/Moderating/ModeratingErrorCodes .cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,10 @@
+﻿using FinkiChattery.Common.Errors;
+
+namespace FinkiChattery.Commands.Moderating
+{
+    public class ModeratingErrorCodes : ErrorCodes
+    {
+        public const string CategoryNameLengthInvalid = "CategoryNameLengthInvalid";
+        public const string CategoryNameAlreadyExists = "CategoryNameAlreadyExists";
+    }
+}
Index: src/FinkiChattery/FinkiChattery.Commands/Moderating/Validators/CategoryWithNameIsUnique.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Commands/Moderating/Validators/CategoryWithNameIsUnique.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/FinkiChattery/FinkiChattery.Commands/Moderating/Validators/CategoryWithNameIsUnique.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,29 @@
+﻿using FinkiChattery.Persistence.UnitOfWork;
+using FluentValidation.Validators;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FinkiChattery.Commands.Moderating.Validators
+{
+    public class CategoryWithNameIsUnique : AsyncValidatorBase
+    {
+        public CategoryWithNameIsUnique(IUnitOfWork unitOfWork)
+        {
+            UnitOfWork = unitOfWork;
+        }
+
+        public IUnitOfWork UnitOfWork { get; }
+
+        protected override async Task<bool> IsValidAsync(PropertyValidatorContext context, CancellationToken cancellation)
+        {
+            var categoryName = (string)context.PropertyValue;
+
+            return await UnitOfWork.Categories.CategoryWithNameIsUnique(categoryName);
+        }
+
+        protected override string GetDefaultMessageTemplate()
+        {
+            return ModeratingErrorCodes.CategoryNameAlreadyExists;
+        }
+    }
+}
Index: src/FinkiChattery/FinkiChattery.Commands/Moderating/Validators/ModeratingFluentValidationRules.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Commands/Moderating/Validators/ModeratingFluentValidationRules.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/FinkiChattery/FinkiChattery.Commands/Moderating/Validators/ModeratingFluentValidationRules.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,12 @@
+﻿using FluentValidation;
+
+namespace FinkiChattery.Commands.Moderating.Validators
+{
+    public static class ModeratingFluentValidationRules
+    {
+        public static IRuleBuilderOptions<T, string> CategoryTitleValidate<T>(this IRuleBuilder<T, string> ruleBuilder)
+        {
+            return ruleBuilder.NotNull().WithMessage(ModeratingErrorCodes.CantBeNull).MaximumLength(500).WithMessage(ModeratingErrorCodes.CategoryNameLengthInvalid);
+        }
+    }
+}
Index: src/FinkiChattery/FinkiChattery.Contracts/Moderating/CreateCategory/CreateCategoryRequest.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Contracts/Moderating/CreateCategory/CreateCategoryRequest.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/FinkiChattery/FinkiChattery.Contracts/Moderating/CreateCategory/CreateCategoryRequest.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,7 @@
+﻿namespace FinkiChattery.Contracts.Moderating
+{
+    public class CreateCategoryRequest
+    {
+        public string Name { get; set; }
+    }
+}
Index: src/FinkiChattery/FinkiChattery.Database/FinkiChattery.Database.sqlproj
===================================================================
--- src/FinkiChattery/FinkiChattery.Database/FinkiChattery.Database.sqlproj	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/FinkiChattery/FinkiChattery.Database/FinkiChattery.Database.sqlproj	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -76,7 +76,7 @@
     <Folder Include="Snapshots" />
     <Folder Include="dbo\Tables\Vote" />
+    <Folder Include="dbo\Tables\Moderator" />
   </ItemGroup>
   <ItemGroup>
-    <Build Include="dbo\Tables\Moderator.sql" />
     <Build Include="dbo\Tables\Teacher.sql" />
     <Build Include="dbo\Tables\StudentTeam.sql" />
@@ -101,4 +101,6 @@
     <None Include="dbo\Tables\QuestionCategory\QuestionCategory.Debug.Seed.sql" />
     <Build Include="dbo\Tables\Vote\Vote.sql" />
+    <Build Include="dbo\Tables\Moderator\Moderator.sql" />
+    <None Include="dbo\Tables\Moderator\Moderator.Debug.Seed.sql" />
   </ItemGroup>
   <ItemGroup>
Index: src/FinkiChattery/FinkiChattery.Database/dbo/Scripts/PostDeploymentScripts/Debug.PostDeployment.sql
===================================================================
--- src/FinkiChattery/FinkiChattery.Database/dbo/Scripts/PostDeploymentScripts/Debug.PostDeployment.sql	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/FinkiChattery/FinkiChattery.Database/dbo/Scripts/PostDeploymentScripts/Debug.PostDeployment.sql	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -6,2 +6,3 @@
 :r ./../../Tables/AnswerResponse/AnswerResponse.Debug.Seed.sql
 :r ./../../Tables/QuestionCategory/QuestionCategory.Debug.Seed.sql
+:r ./../../Tables/Moderator/Moderator.Debug.Seed.sql
Index: src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Moderator.sql
===================================================================
--- src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Moderator.sql	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ 	(revision )
@@ -1,13 +1,0 @@
-﻿CREATE TABLE [dbo].[Moderator] (
-    [Id]                BIGINT           IDENTITY (1, 1) NOT NULL,
-    [Uid]               UNIQUEIDENTIFIER NOT NULL,
-    [ApplicationUserFk] BIGINT           NOT NULL,
-    CONSTRAINT [PK_Moderator] PRIMARY KEY CLUSTERED ([Id] ASC),
-    CONSTRAINT [FK_Moderator_AspNetUsers_ApplicationUserFk] FOREIGN KEY ([ApplicationUserFk]) REFERENCES [dbo].[AspNetUsers] ([Id])
-);
-
-
-GO
-CREATE UNIQUE NONCLUSTERED INDEX [IX_Moderator_ApplicationUserFk]
-    ON [dbo].[Moderator]([ApplicationUserFk] ASC);
-
Index: src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Moderator/Moderator.Debug.Seed.sql
===================================================================
--- src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Moderator/Moderator.Debug.Seed.sql	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Moderator/Moderator.Debug.Seed.sql	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,27 @@
+﻿BEGIN
+    SET IDENTITY_INSERT [dbo].[Moderator] ON
+    MERGE [dbo].[Moderator] AS T
+    USING
+    (
+        SELECT *
+        FROM
+    (
+        VALUES
+            (1, N'aee193c3-9d36-4ed8-81b2-15eb4ff305f1', 2)
+    ) AS temp ([Id], [Uid], [ApplicationUserFk])
+    ) AS S
+    ON T.[ID] = S.[ID]
+    WHEN MATCHED THEN
+        UPDATE SET T.[Uid] = S.[Uid],
+                   T.[ApplicationUserFk] = S.[ApplicationUserFk]
+    WHEN NOT MATCHED THEN
+        INSERT
+        (
+            [Id],
+            [Uid],
+            [ApplicationUserFk]
+        )
+        VALUES
+        (S.[Id], S.[Uid], S.[ApplicationUserFk]);
+    SET IDENTITY_INSERT [dbo].[Moderator] OFF
+END
Index: src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Moderator/Moderator.sql
===================================================================
--- src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Moderator/Moderator.sql	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
+++ src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Moderator/Moderator.sql	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -0,0 +1,13 @@
+﻿CREATE TABLE [dbo].[Moderator] (
+    [Id]                BIGINT           IDENTITY (1, 1) NOT NULL,
+    [Uid]               UNIQUEIDENTIFIER NOT NULL,
+    [ApplicationUserFk] BIGINT           NOT NULL,
+    CONSTRAINT [PK_Moderator] PRIMARY KEY CLUSTERED ([Id] ASC),
+    CONSTRAINT [FK_Moderator_AspNetUsers_ApplicationUserFk] FOREIGN KEY ([ApplicationUserFk]) REFERENCES [dbo].[AspNetUsers] ([Id])
+);
+
+
+GO
+CREATE UNIQUE NONCLUSTERED INDEX [IX_Moderator_ApplicationUserFk]
+    ON [dbo].[Moderator]([ApplicationUserFk] ASC);
+
Index: src/FinkiChattery/FinkiChattery.Database/dbo/Tables/User/Seed/Users.Debug.Seed.sql
===================================================================
--- src/FinkiChattery/FinkiChattery.Database/dbo/Tables/User/Seed/Users.Debug.Seed.sql	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/FinkiChattery/FinkiChattery.Database/dbo/Tables/User/Seed/Users.Debug.Seed.sql	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -7,5 +7,6 @@
 	FROM (
 	VALUES
-		(1, N'stojkovmarko1@gmail.com',  N'STOJKOVMARKO1@GMAIL.COM', 'stojkovmarko1@gmail.com',  N'STOJKOVMARKO1@GMAIL.COM', 1, N'AQAAAAEAACcQAAAAELBRjOGmA/Dh8BPvcPMA1vmk1jjvyDd/9/lO/3shoBt7z9NfiKJR+Ckp/2+6BVpyLw==', N'MMDEZ3RWADCRM4PTTKSEZNQYNH5V7UVA', N'08309369-24a1-470c-9ab1-65a250cafd4e', null, 0, 0, null, 1, 0, 0)
+		(1, N'stojkovmarko1@gmail.com',  N'STOJKOVMARKO1@GMAIL.COM', 'stojkovmarko1@gmail.com',  N'STOJKOVMARKO1@GMAIL.COM', 1, N'AQAAAAEAACcQAAAAELBRjOGmA/Dh8BPvcPMA1vmk1jjvyDd/9/lO/3shoBt7z9NfiKJR+Ckp/2+6BVpyLw==', N'MMDEZ3RWADCRM4PTTKSEZNQYNH5V7UVA', N'08309369-24a1-470c-9ab1-65a250cafd4e', null, 0, 0, null, 1, 0, 0),
+		(2, N'stojkovmarko1234@gmail.com',  N'STOJKOVMARKO1234@GMAIL.COM', 'stojkovmarko1234@gmail.com',  N'STOJKOVMARKO1234@GMAIL.COM', 1, N'AQAAAAEAACcQAAAAELBRjOGmA/Dh8BPvcPMA1vmk1jjvyDd/9/lO/3shoBt7z9NfiKJR+Ckp/2+6BVpyLw==', N'MMDEZ3RWADCRM4PTTKSEZNQYNH5V7UVA', N'08309369-24a1-470c-9ab1-65a250cafd4e', null, 0, 0, null, 1, 0, 2)
 		)
 		AS temp ([ID], [UserName], [NormalizedUserName], [Email], [NormalizedEmail], [EmailConfirmed], [PasswordHash], [SecurityStamp], [ConcurrencyStamp], [PhoneNumber], [PhoneNumberConfirmed], [TwoFactorEnabled], [LockoutEnd], [LockoutEnabled], [AccessFailedCount], [Role])
Index: src/FinkiChattery/FinkiChattery.Persistence/Models/Category.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Persistence/Models/Category.cs	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/FinkiChattery/FinkiChattery.Persistence/Models/Category.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -1,12 +1,10 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace FinkiChattery.Persistence.Models
+﻿namespace FinkiChattery.Persistence.Models
 {
     public class Category : BaseEntity
     {
+        public Category() : base()
+        {
+        }
+
         public string Name { get; set; }
     }
Index: src/FinkiChattery/FinkiChattery.Persistence/Repositories/Contracts/ICategoriesRepo.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Persistence/Repositories/Contracts/ICategoriesRepo.cs	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/FinkiChattery/FinkiChattery.Persistence/Repositories/Contracts/ICategoriesRepo.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -12,4 +12,6 @@
         public Task<bool> CategoriesExist(IEnumerable<Guid> categoriesUids);
 
+        public Task<bool> CategoryWithNameIsUnique(string name);
+
         public Task<IEnumerable<Category>> GetCategories(IEnumerable<Guid> categoriesUids);
     }
Index: src/FinkiChattery/FinkiChattery.Persistence/Repositories/Implementations/CategoriesRepo.cs
===================================================================
--- src/FinkiChattery/FinkiChattery.Persistence/Repositories/Implementations/CategoriesRepo.cs	(revision fcc308081d20fa447cc6c3c173092078ab635664)
+++ src/FinkiChattery/FinkiChattery.Persistence/Repositories/Implementations/CategoriesRepo.cs	(revision f3c4950cc1a46557f6c15359e067de8c9e5e179a)
@@ -20,4 +20,9 @@
         }
 
+        public async Task<bool> CategoryWithNameIsUnique(string name)
+        {
+            return !(await DbSet.AnyAsync(x => x.Name == name));
+        }
+
         public async Task<IEnumerable<Category>> GetCategories(IEnumerable<Guid> categoriesUids)
         {
