mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender-pwa.git
synced 2025-08-03 18:29:16 +02:00
98 implement anonymized DTO events
This commit is contained in:
@@ -2,6 +2,7 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"slices"
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pocketbase/pocketbase/models"
|
"github.com/pocketbase/pocketbase/models"
|
||||||
"github.com/pocketbase/pocketbase/tools/types"
|
"github.com/pocketbase/pocketbase/tools/types"
|
||||||
@@ -13,21 +14,30 @@ func (m Events) Contains(event Event) bool {
|
|||||||
return slices.Contains(m, event)
|
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 {
|
type Event struct {
|
||||||
UUID string `db:"uuid" json:"uuid"`
|
UUID string `db:"uuid" json:"uuid"`
|
||||||
Day string `db:"Day" json:"day"`
|
Day string `db:"Day" json:"day"`
|
||||||
Week string `db:"Week" json:"week"`
|
Week string `db:"Week" json:"week"`
|
||||||
Start types.DateTime `db:"start" json:"start"`
|
Start types.DateTime `db:"start" json:"start"`
|
||||||
End types.DateTime `db:"end" json:"end"`
|
End types.DateTime `db:"end" json:"end"`
|
||||||
Name string `db:"Name" json:"name"`
|
Name string `db:"Name" json:"name"`
|
||||||
EventType string `db:"EventType" json:"eventType"`
|
EventType string `db:"EventType" json:"eventType"`
|
||||||
Compulsory string `db:"Compulsory" json:"compulsory"`
|
Compulsory string `db:"Compulsory" json:"compulsory"`
|
||||||
Prof string `db:"Prof" json:"prof"`
|
Prof string `db:"Prof" json:"prof"`
|
||||||
Rooms string `db:"Rooms" json:"rooms"`
|
Rooms string `db:"Rooms" json:"rooms"`
|
||||||
Notes string `db:"Notes" json:"notes"`
|
Notes string `db:"Notes" json:"notes"`
|
||||||
BookedAt string `db:"BookedAt" json:"bookedAt"`
|
BookedAt string `db:"BookedAt" json:"bookedAt"`
|
||||||
Course string `db:"course" json:"course"`
|
Course string `db:"course" json:"course"`
|
||||||
Semester string `db:"semester" json:"semester"`
|
Semester string `db:"semester" json:"semester"`
|
||||||
models.BaseModel
|
models.BaseModel
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,3 +62,15 @@ func (m *Event) SetCourse(course string) Event {
|
|||||||
m.Course = course
|
m.Course = course
|
||||||
return *m
|
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
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pocketbase/pocketbase/models"
|
"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
|
package room
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/labstack/echo/v5"
|
"htwkalender/model"
|
||||||
"github.com/pocketbase/pocketbase"
|
|
||||||
"htwkalender/service/db"
|
"htwkalender/service/db"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/labstack/echo/v5"
|
||||||
|
"github.com/pocketbase/pocketbase"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetRooms(c echo.Context, app *pocketbase.PocketBase) error {
|
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 {
|
func GetRoomScheduleForDay(c echo.Context, app *pocketbase.PocketBase, room string, date string) error {
|
||||||
events := db.GetRoomScheduleForDay(app, room, date)
|
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 {
|
func GetRoomSchedule(c echo.Context, app *pocketbase.PocketBase, room string, from string, to string) error {
|
||||||
events := db.GetRoomSchedule(app, room, from, to)
|
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[]> {
|
export async function fetchRoom(): Promise<string[]> {
|
||||||
const rooms: string[] = [];
|
const rooms: string[] = [];
|
||||||
@@ -16,8 +16,8 @@ export async function fetchEventsByRoomAndDuration(
|
|||||||
room: string,
|
room: string,
|
||||||
from_date: string,
|
from_date: string,
|
||||||
to_date: string,
|
to_date: string,
|
||||||
): Promise<Event[]> {
|
): Promise<AnonymizedEventDTO[]> {
|
||||||
const events: Event[] = [];
|
const events: AnonymizedEventDTO[] = [];
|
||||||
await fetch(
|
await fetch(
|
||||||
"/api/schedule?room=" + room + "&from=" + from_date + "&to=" + to_date,
|
"/api/schedule?room=" + room + "&from=" + from_date + "&to=" + to_date,
|
||||||
)
|
)
|
||||||
@@ -27,7 +27,7 @@ export async function fetchEventsByRoomAndDuration(
|
|||||||
})
|
})
|
||||||
.then((eventsResponse) => {
|
.then((eventsResponse) => {
|
||||||
console.log("Response:", eventsResponse);
|
console.log("Response:", eventsResponse);
|
||||||
eventsResponse.forEach((event: Event) => events.push(event));
|
eventsResponse.forEach((event: AnonymizedEventDTO) => events.push(event));
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log("Error fetching events: ", error);
|
console.log("Error fetching events: ", error);
|
||||||
|
@@ -52,7 +52,7 @@ async function getOccupation() {
|
|||||||
id: index,
|
id: index,
|
||||||
start: event.start.replace(/\s\+\d{4}\s\w+$/, "").replace(" ", "T"),
|
start: event.start.replace(/\s\+\d{4}\s\w+$/, "").replace(" ", "T"),
|
||||||
end: event.end.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,
|
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