mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender.git
synced 2025-08-02 17:59:14 +02:00
Merge pull request #110 from HTWK-Leipzig/98-roomfinder-restricted-data-access
98 implement anonymized DTO events
This commit is contained in:
@@ -2,6 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
@@ -13,21 +14,30 @@ func (m Events) Contains(event Event) bool {
|
||||
return slices.Contains(m, event)
|
||||
}
|
||||
|
||||
type AnonymizedEventDTO struct {
|
||||
Day string `db:"Day" json:"day"`
|
||||
Week string `db:"Week" json:"week"`
|
||||
Start types.DateTime `db:"start" json:"start"`
|
||||
End types.DateTime `db:"end" json:"end"`
|
||||
Rooms string `db:"Rooms" json:"rooms"`
|
||||
Free bool `json:"free"`
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
UUID string `db:"uuid" json:"uuid"`
|
||||
Day string `db:"Day" json:"day"`
|
||||
Week string `db:"Week" json:"week"`
|
||||
Start types.DateTime `db:"start" json:"start"`
|
||||
End types.DateTime `db:"end" json:"end"`
|
||||
Name string `db:"Name" json:"name"`
|
||||
EventType string `db:"EventType" json:"eventType"`
|
||||
Compulsory string `db:"Compulsory" json:"compulsory"`
|
||||
Prof string `db:"Prof" json:"prof"`
|
||||
Rooms string `db:"Rooms" json:"rooms"`
|
||||
Notes string `db:"Notes" json:"notes"`
|
||||
BookedAt string `db:"BookedAt" json:"bookedAt"`
|
||||
Course string `db:"course" json:"course"`
|
||||
Semester string `db:"semester" json:"semester"`
|
||||
UUID string `db:"uuid" json:"uuid"`
|
||||
Day string `db:"Day" json:"day"`
|
||||
Week string `db:"Week" json:"week"`
|
||||
Start types.DateTime `db:"start" json:"start"`
|
||||
End types.DateTime `db:"end" json:"end"`
|
||||
Name string `db:"Name" json:"name"`
|
||||
EventType string `db:"EventType" json:"eventType"`
|
||||
Compulsory string `db:"Compulsory" json:"compulsory"`
|
||||
Prof string `db:"Prof" json:"prof"`
|
||||
Rooms string `db:"Rooms" json:"rooms"`
|
||||
Notes string `db:"Notes" json:"notes"`
|
||||
BookedAt string `db:"BookedAt" json:"bookedAt"`
|
||||
Course string `db:"course" json:"course"`
|
||||
Semester string `db:"semester" json:"semester"`
|
||||
models.BaseModel
|
||||
}
|
||||
|
||||
@@ -52,3 +62,15 @@ func (m *Event) SetCourse(course string) Event {
|
||||
m.Course = course
|
||||
return *m
|
||||
}
|
||||
|
||||
// Creates an AnonymizedEventDTO from an Event hiding all sensitive data
|
||||
func (m *Event) AnonymizeEvent() AnonymizedEventDTO {
|
||||
return AnonymizedEventDTO{
|
||||
Day: m.Day,
|
||||
Week: m.Week,
|
||||
Start: m.Start,
|
||||
End: m.End,
|
||||
Rooms: m.Rooms,
|
||||
Free: strings.Contains(strings.ToLower(m.Name), "zur freien verfügung"),
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
@@ -126,3 +127,73 @@ func TestEvent_Equals(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvent_AnonymizeEvent(t *testing.T) {
|
||||
type fields struct {
|
||||
UUID string
|
||||
Day string
|
||||
Week string
|
||||
Start types.DateTime
|
||||
End types.DateTime
|
||||
Name string
|
||||
EventType string
|
||||
Compulsory string
|
||||
Prof string
|
||||
Rooms string
|
||||
Notes string
|
||||
BookedAt string
|
||||
Course string
|
||||
Semester string
|
||||
BaseModel models.BaseModel
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want AnonymizedEventDTO
|
||||
}{
|
||||
{
|
||||
name: "empty event",
|
||||
fields: fields{},
|
||||
want: AnonymizedEventDTO{Day: "", Week: "", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "", Free: false},
|
||||
},
|
||||
{
|
||||
name: "one event",
|
||||
fields: fields{Name: "Event", Day: "test", Week: "test", Rooms: "test"},
|
||||
want: AnonymizedEventDTO{Day: "test", Week: "test", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "test", Free: false},
|
||||
},
|
||||
{
|
||||
name: "one event with free",
|
||||
fields: fields{Name: "Räume zur freien Verfügung", Day: "test", Week: "test", Rooms: "test", Course: "test"},
|
||||
want: AnonymizedEventDTO{Day: "test", Week: "test", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "test", Free: true},
|
||||
},
|
||||
{
|
||||
name: "another free event",
|
||||
fields: fields{Name: "Zur freien Verfügung", Day: "Montag", Week: "5", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "TR_A1.28-S", Course: "42INM-3"},
|
||||
want: AnonymizedEventDTO{Day: "Montag", Week: "5", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "TR_A1.28-S", Free: true},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &Event{
|
||||
UUID: tt.fields.UUID,
|
||||
Day: tt.fields.Day,
|
||||
Week: tt.fields.Week,
|
||||
Start: tt.fields.Start,
|
||||
End: tt.fields.End,
|
||||
Name: tt.fields.Name,
|
||||
EventType: tt.fields.EventType,
|
||||
Compulsory: tt.fields.Compulsory,
|
||||
Prof: tt.fields.Prof,
|
||||
Rooms: tt.fields.Rooms,
|
||||
Notes: tt.fields.Notes,
|
||||
BookedAt: tt.fields.BookedAt,
|
||||
Course: tt.fields.Course,
|
||||
Semester: tt.fields.Semester,
|
||||
BaseModel: tt.fields.BaseModel,
|
||||
}
|
||||
if got := m.AnonymizeEvent(); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Event.AnonymizeEvent() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,12 @@
|
||||
package room
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"htwkalender/model"
|
||||
"htwkalender/service/db"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
)
|
||||
|
||||
func GetRooms(c echo.Context, app *pocketbase.PocketBase) error {
|
||||
@@ -14,10 +16,19 @@ func GetRooms(c echo.Context, app *pocketbase.PocketBase) error {
|
||||
|
||||
func GetRoomScheduleForDay(c echo.Context, app *pocketbase.PocketBase, room string, date string) error {
|
||||
events := db.GetRoomScheduleForDay(app, room, date)
|
||||
return c.JSON(http.StatusOK, events)
|
||||
return c.JSON(http.StatusOK, anonymizeRooms(events))
|
||||
}
|
||||
|
||||
func GetRoomSchedule(c echo.Context, app *pocketbase.PocketBase, room string, from string, to string) error {
|
||||
events := db.GetRoomSchedule(app, room, from, to)
|
||||
return c.JSON(http.StatusOK, events)
|
||||
return c.JSON(http.StatusOK, anonymizeRooms(events))
|
||||
}
|
||||
|
||||
// Transform the events to anonymized events throwing away all unnecessary information
|
||||
func anonymizeRooms(events []model.Event) []model.AnonymizedEventDTO {
|
||||
var anonymizedEvents = []model.AnonymizedEventDTO{}
|
||||
for _, event := range events {
|
||||
anonymizedEvents = append(anonymizedEvents, event.AnonymizeEvent())
|
||||
}
|
||||
return anonymizedEvents
|
||||
}
|
||||
|
125
backend/service/room/roomService_test.go
Normal file
125
backend/service/room/roomService_test.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package room
|
||||
|
||||
import (
|
||||
"htwkalender/model"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
)
|
||||
|
||||
func Test_anonymizeRooms(t *testing.T) {
|
||||
type args struct {
|
||||
events []model.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []model.AnonymizedEventDTO
|
||||
}{
|
||||
{
|
||||
name: "anonymize single event",
|
||||
args: args{
|
||||
events: []model.Event{
|
||||
{
|
||||
UUID: "testUUID",
|
||||
Day: "Montag",
|
||||
Week: "52",
|
||||
Start: types.DateTime{},
|
||||
End: types.DateTime{},
|
||||
Name: "Secret",
|
||||
EventType: "V",
|
||||
Prof: "Prof. Dr. Secret",
|
||||
Rooms: "Room",
|
||||
Notes: "Secret",
|
||||
BookedAt: "Secret",
|
||||
Course: "42INM-3",
|
||||
Semester: "ws",
|
||||
Compulsory: "p",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []model.AnonymizedEventDTO{
|
||||
{
|
||||
Day: "Montag",
|
||||
Week: "52",
|
||||
Start: types.DateTime{},
|
||||
End: types.DateTime{},
|
||||
Rooms: "Room",
|
||||
Free: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "anonymize empty list",
|
||||
args: args{
|
||||
events: []model.Event{},
|
||||
},
|
||||
want: []model.AnonymizedEventDTO{},
|
||||
},
|
||||
{
|
||||
name: "anonymize multiple events",
|
||||
args: args{
|
||||
events: []model.Event{
|
||||
{
|
||||
UUID: "testUUID1",
|
||||
Day: "Montag",
|
||||
Week: "51",
|
||||
Start: types.DateTime{},
|
||||
End: types.DateTime{},
|
||||
Name: "Incognito",
|
||||
EventType: "V",
|
||||
Prof: "Prof. Dr. Incognito",
|
||||
Rooms: "Room",
|
||||
Notes: "Incognito",
|
||||
BookedAt: "Incognito",
|
||||
Course: "69INM-2",
|
||||
Semester: "sose",
|
||||
Compulsory: "p",
|
||||
},
|
||||
{
|
||||
UUID: "testUUID2",
|
||||
Day: "Dienstag",
|
||||
Week: "52",
|
||||
Start: types.DateTime{},
|
||||
End: types.DateTime{},
|
||||
Name: "Private",
|
||||
EventType: "S",
|
||||
Prof: "Prof.In. Dr.-Ing. Private",
|
||||
Rooms: "Room",
|
||||
Notes: "Private",
|
||||
BookedAt: "Private",
|
||||
Course: "42MIM-3",
|
||||
Semester: "ws",
|
||||
Compulsory: "w",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []model.AnonymizedEventDTO{
|
||||
{
|
||||
Day: "Montag",
|
||||
Week: "51",
|
||||
Start: types.DateTime{},
|
||||
End: types.DateTime{},
|
||||
Rooms: "Room",
|
||||
Free: false,
|
||||
},
|
||||
{
|
||||
Day: "Dienstag",
|
||||
Week: "52",
|
||||
Start: types.DateTime{},
|
||||
End: types.DateTime{},
|
||||
Rooms: "Room",
|
||||
Free: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := anonymizeRooms(tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("anonymizeRooms() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
import { Event } from "../model/event.ts";
|
||||
import { AnonymizedEventDTO } from "../model/event.ts";
|
||||
|
||||
export async function fetchRoom(): Promise<string[]> {
|
||||
const rooms: string[] = [];
|
||||
@@ -16,8 +16,8 @@ export async function fetchEventsByRoomAndDuration(
|
||||
room: string,
|
||||
from_date: string,
|
||||
to_date: string,
|
||||
): Promise<Event[]> {
|
||||
const events: Event[] = [];
|
||||
): Promise<AnonymizedEventDTO[]> {
|
||||
const events: AnonymizedEventDTO[] = [];
|
||||
await fetch(
|
||||
"/api/schedule?room=" + room + "&from=" + from_date + "&to=" + to_date,
|
||||
)
|
||||
@@ -27,7 +27,7 @@ export async function fetchEventsByRoomAndDuration(
|
||||
})
|
||||
.then((eventsResponse) => {
|
||||
console.log("Response:", eventsResponse);
|
||||
eventsResponse.forEach((event: Event) => events.push(event));
|
||||
eventsResponse.forEach((event: AnonymizedEventDTO) => events.push(event));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("Error fetching events: ", error);
|
||||
|
@@ -52,7 +52,7 @@ async function getOccupation() {
|
||||
id: index,
|
||||
start: event.start.replace(/\s\+\d{4}\s\w+$/, "").replace(" ", "T"),
|
||||
end: event.end.replace(/\s\+\d{4}\s\w+$/, "").replace(" ", "T"),
|
||||
showFree: event.name.toLowerCase().includes("zur freien verfügung"),
|
||||
showFree: event.free
|
||||
};
|
||||
});
|
||||
|
||||
|
@@ -14,3 +14,14 @@ export class Event {
|
||||
public week: string,
|
||||
) {}
|
||||
}
|
||||
|
||||
export class AnonymizedEventDTO {
|
||||
constructor(
|
||||
public day: string,
|
||||
public week: string,
|
||||
public start: string,
|
||||
public end: string,
|
||||
public rooms: string,
|
||||
public free: boolean
|
||||
) {}
|
||||
}
|
||||
|
Reference in New Issue
Block a user