Merge pull request #77 from HTWK-Leipzig/74-security-for-endpoints

74 security for endpoints
This commit is contained in:
masterElmar
2023-11-20 17:40:58 +01:00
committed by GitHub
7 changed files with 206 additions and 31 deletions

View File

@@ -35,6 +35,14 @@ htwkalender-demo
Execute the following api calls to fetch data manually from HTWK and store it in the database: Execute the following api calls to fetch data manually from HTWK and store it in the database:
Both api calls need a token to be executed.
You can get a token by logging in to the admin ui and copy the token from the local storage.
Add this attribute to the request header of the api call:
```
Authorization : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MDE3MDA3ODQsImlkIjoicnA0Ym54YXNyczM5emR4IiwidHlwZSI6ImFkbWluIn0.j7Bt3-uaZ8CoNt8D9Oxjk7ZwvHDGZJy1xe3aq4BID3w
```
The first command will fetch all groups and store them in the database. The first command will fetch all groups and store them in the database.
This should be done quick in a few seconds (0-5s). This should be done quick in a few seconds (0-5s).
When you execute the command again, it will update the groups in the When you execute the command again, it will update the groups in the

View File

@@ -1,10 +1,10 @@
package model package model
type Module struct { type Module struct {
UUID string `json:"uuid"` UUID string `json:"uuid" db:"uuid"`
Name string `json:"name"` Name string `json:"name" db:"Name"`
Prof string `json:"prof"` Prof string `json:"prof" db:"Prof"`
Course string `json:"course"` Course string `json:"course" db:"course"`
Semester string `json:"semester"` Semester string `json:"semester" db:"semester"`
Events Events `json:"events"` Events Events `json:"events"`
} }

View File

@@ -11,30 +11,150 @@ paths:
/api/fetchPlans: /api/fetchPlans:
get: get:
summary: Fetch Seminar Plans summary: Fetch Seminar Plans
security:
- ApiKeyAuth: []
responses: responses:
'200': '200':
description: Successful response description: Successful response
/api/fetchGroups: /api/fetchGroups:
get: get:
summary: Fetch Seminar Groups summary: Fetch Seminar Groups
security:
- ApiKeyAuth: []
responses: responses:
'200': '200':
description: Successful response description: Successful response
/api/modules:
delete:
summary: Delete Module
security:
- ApiKeyAuth: []
responses:
'200':
description: Successful response
/api/rooms: /api/rooms:
get: get:
summary: Get Rooms summary: Get Rooms
responses: responses:
'200': '200':
description: Successful response description: Successful response
/api/feedURL: /api/schedule/day:
get: get:
summary: Get iCal Feed URL summary: Get Day Schedule
parameters:
- name: room
in: query
description: room
example: "LN006-H"
required: true
schema:
type: string
- name: date
in: query
description: date
example: "2023-11-26"
required: true
schema:
type: string
responses:
'200':
description: Successful response
/api/schedule:
get:
summary: Get Schedule
parameters:
- name: room
in: query
description: room
example: "LN006-H"
required: true
schema:
type: string
- name: from
in: query
description: date
example: "2023-11-26"
required: true
schema:
type: string
- name: to
in: query
description: date
example: "2023-11-30"
required: true
schema:
type: string
responses:
'200':
description: Successful response
/api/createFeed:
post:
summary: Create iCal Feed
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Module'
required:
- name
- modules
responses: responses:
'200': '200':
description: Successful response description: Successful response
/api/feed: /api/feed:
get: get:
summary: Get iCal Feed for calendar summary: Get iCal Feed for calendar
parameters:
- name: token
in: query
description: calendar token
required: true
example: "ldluwzg3e73ffxq"
schema:
type: string
responses:
'200':
description: Successful response
/api/course/modules:
get:
summary: Get Modules for Course
parameters:
- name: course
in: query
description: course
required: true
example: "Software Engineering"
schema:
type: string
- name: semester
in: query
description: semester
required: true
example: "ws"
schema:
type: string
responses:
'200':
description: Successful response
/api/module:
get:
summary: Get Module
parameters:
- name: uuid
in: query
description: uuid
required: true
example: "d0b3a0e0-2f1a-4e1a-8b0a-0b9e1a0b9e1a"
schema:
type: string
responses:
'200':
description: Successful response
/api/courses:
get:
summary: Get Courses
responses: responses:
'200': '200':
description: Successful response description: Successful response
@@ -51,3 +171,52 @@ paths:
responses: responses:
'200': '200':
description: Successful response description: Successful response
/api/events:
delete:
summary: Delete Event
security:
- ApiKeyAuth: []
responses:
'200':
description: Successful response
/api/feeds/migrate:
get:
summary: Migrates all iCal Feeds in the database to the new format
security:
- ApiKeyAuth: []
responses:
'200':
description: Successful response
security:
- ApiKeyAuth: []
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: Authorization
schemas:
Module:
type: object
properties:
name:
type: string
description: name
example: "Software Engineering"
uuid:
type: string
format: uuid
course:
type: string
userDefinedName:
type: string
prof:
type: string
semester:
type: string
reminder:
type: boolean
events:
type: array
items:
type: string

View File

@@ -1,7 +1,6 @@
package service package service
import ( import (
"htwkalender/model"
"htwkalender/service/events" "htwkalender/service/events"
"htwkalender/service/fetch" "htwkalender/service/fetch"
"htwkalender/service/ical" "htwkalender/service/ical"
@@ -26,6 +25,7 @@ func AddRoutes(app *pocketbase.PocketBase) {
}, },
Middlewares: []echo.MiddlewareFunc{ Middlewares: []echo.MiddlewareFunc{
apis.ActivityLogger(app), apis.ActivityLogger(app),
apis.RequireAdminAuth(),
}, },
}) })
if err != nil { if err != nil {
@@ -61,6 +61,7 @@ func AddRoutes(app *pocketbase.PocketBase) {
}, },
Middlewares: []echo.MiddlewareFunc{ Middlewares: []echo.MiddlewareFunc{
apis.ActivityLogger(app), apis.ActivityLogger(app),
apis.RequireAdminAuth(),
}, },
}) })
if err != nil { if err != nil {
@@ -212,18 +213,11 @@ func AddRoutes(app *pocketbase.PocketBase) {
app.OnBeforeServe().Add(func(e *core.ServeEvent) error { app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
_, err := e.Router.AddRoute(echo.Route{ _, err := e.Router.AddRoute(echo.Route{
Method: http.MethodPost, Method: http.MethodGet,
Path: "/api/module", Path: "/api/module",
Handler: func(c echo.Context) error { Handler: func(c echo.Context) error {
requestModule := c.QueryParam("uuid")
var requestModule model.Module module, err := events.GetModuleByUUID(app, requestModule)
if err := c.Bind(&requestModule); err != nil {
return apis.NewBadRequestError("Failed to read request body", err)
}
module, err := events.GetModuleByName(app, requestModule)
if err != nil { if err != nil {
return c.JSON(400, err) return c.JSON(400, err)
} else { } else {
@@ -286,7 +280,7 @@ func AddRoutes(app *pocketbase.PocketBase) {
app.OnBeforeServe().Add(func(e *core.ServeEvent) error { app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
_, err := e.Router.AddRoute(echo.Route{ _, err := e.Router.AddRoute(echo.Route{
Method: http.MethodGet, Method: http.MethodGet,
Path: "/api/feed/migrate", Path: "/api/feeds/migrate",
Handler: func(c echo.Context) error { Handler: func(c echo.Context) error {
err := ical.MigrateFeedJson(app) err := ical.MigrateFeedJson(app)

View File

@@ -196,6 +196,18 @@ func DeleteAllEvents(app *pocketbase.PocketBase) error {
return nil return nil
} }
func FindModuleByUUID(app *pocketbase.PocketBase, uuid string) (model.Module, error) {
var module model.Module
err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("uuid = {:uuid}", dbx.Params{"uuid": uuid})).One(&module)
if err != nil {
print("Error while getting events from database: ", err)
return model.Module{}, err
}
return module, nil
}
func FindAllEventsByModule(app *pocketbase.PocketBase, module model.Module) (model.Events, error) { func FindAllEventsByModule(app *pocketbase.PocketBase, module model.Module) (model.Events, error) {
var events model.Events var events model.Events

View File

@@ -42,11 +42,8 @@ func GetAllModulesDistinct(app *pocketbase.PocketBase, c echo.Context) error {
} }
} }
// GetModuleByName returns a module by its name func GetModuleByUUID(app *pocketbase.PocketBase, uuid string) (model.Module, error) {
// If the module does not exist, an error is returned module, err := db.FindModuleByUUID(app, uuid)
// If the module exists, the module is returned
// Module is a struct that exists in database as events
func GetModuleByName(app *pocketbase.PocketBase, module model.Module) (model.Module, error) {
events, err := db.FindAllEventsByModule(app, module) events, err := db.FindAllEventsByModule(app, module)
if err != nil || len(events) == 0 { if err != nil || len(events) == 0 {

View File

@@ -1,13 +1,8 @@
import { Module } from "../model/module"; import { Module } from "../model/module";
export async function fetchModule(module: Module): Promise<Module> { export async function fetchModule(module: Module): Promise<Module> {
const request = new Request("/api/module", { // request to the backend on /api/module with query parameters name as the module name
method: "POST", const request = new Request("/api/module?uuid=" + module.uuid);
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(module),
});
return await fetch(request) return await fetch(request)
.then((response) => { .then((response) => {