Skip to content
Merged
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
2 changes: 1 addition & 1 deletion backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/go-chi/render v1.0.2
github.com/google/go-cmp v0.6.0
github.com/mitchellh/mapstructure v1.5.0
github.com/privacy-pal/privacy-pal/go v1.0.0
github.com/privacy-pal/privacy-pal/go v1.3.0
github.com/rs/cors v1.8.3
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb
google.golang.org/grpc v1.58.3
Expand Down
6 changes: 6 additions & 0 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ github.com/privacy-pal/privacy-pal/go v0.6.0 h1:ShjRa0vO+CBPJgD/B1OjiIBfit8B8bu7
github.com/privacy-pal/privacy-pal/go v0.6.0/go.mod h1:iVFaK4o+EYLTOyetSv6pjtWGcmPcTMXL6oUNHVyhoX0=
github.com/privacy-pal/privacy-pal/go v1.0.0 h1:Oti8tPCzAxKzqb9EPP6l1E4P5gJZbL10gHRkoEn7Kxo=
github.com/privacy-pal/privacy-pal/go v1.0.0/go.mod h1:iVFaK4o+EYLTOyetSv6pjtWGcmPcTMXL6oUNHVyhoX0=
github.com/privacy-pal/privacy-pal/go v1.1.0 h1:Fm03J8kbOuuQxV8ayvf+NJSCdToQt0FI2r1SLKfzthA=
github.com/privacy-pal/privacy-pal/go v1.1.0/go.mod h1:4mjmDe2nLDBPMuhiOx1GIy04AQaBWzRUL1YOUZTEi0o=
github.com/privacy-pal/privacy-pal/go v1.2.0 h1:hGRYynIM7NScP/CJ8b2TY8SxndK+kc0kCvnyc3IcOGM=
github.com/privacy-pal/privacy-pal/go v1.2.0/go.mod h1:6wbYoDZiD/AxJI0K2/futdQKCrAR4BHxb7TDgdnOGBU=
github.com/privacy-pal/privacy-pal/go v1.3.0 h1:7Pn2IE62KVIcdhab5xIL+IdF0Tv7jmgoCMsh7iCMO5A=
github.com/privacy-pal/privacy-pal/go v1.3.0/go.mod h1:6wbYoDZiD/AxJI0K2/futdQKCrAR4BHxb7TDgdnOGBU=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo=
github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
Expand Down
23 changes: 20 additions & 3 deletions backend/pkg/privacy/assignment.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package privacy

import (
"cloud.google.com/go/firestore"
pal "github.com/privacy-pal/privacy-pal/go/pkg"
)

func accessAssignment(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) map[string]interface{} {
data := map[string]interface{}{
func handleAccessAssignment(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (data map[string]interface{}, err error) {
data = map[string]interface{}{
"name": dbObj["name"],
"optional": dbObj["optional"],
"maxScore": dbObj["maxScore"],
Expand All @@ -14,5 +15,21 @@ func accessAssignment(dataSubjectId string, currentDbObjLocator pal.Locator, dbO
"grade": dbObj["grades"].(map[string]interface{})[dataSubjectId],
}

return data
return
}

func handleDeleteAssignment(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (nodesToTraverse []pal.Locator, deleteNode bool, fieldsToUpdate pal.FieldUpdates, err error) {
deleteNode = false

// remove grades[dataSubjectId] if exists
fieldsToUpdate = pal.FieldUpdates{
FirestoreUpdates: []firestore.Update{
{
Path: "grades." + dataSubjectId,
Value: firestore.Delete,
},
},
}

return
}
53 changes: 50 additions & 3 deletions backend/pkg/privacy/course.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package privacy

import (
"cloud.google.com/go/firestore"
"github.com/fullstackatbrown/here/pkg/models"
pal "github.com/privacy-pal/privacy-pal/go/pkg"
)

func accessCourse(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) map[string]interface{} {
data := map[string]interface{}{
func handleAccessCourse(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (data map[string]interface{}, err error) {
data = map[string]interface{}{
"title": dbObj["title"],
}

Expand Down Expand Up @@ -45,5 +46,51 @@ func accessCourse(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj p
},
}

return data
return
}

func handleDeleteCourse(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (nodesToTraverse []pal.Locator, deleteNode bool, fieldsToUpdate pal.FieldUpdates, err error) {
deleteNode = false

updates := []firestore.Update{}
// remove student associated with dataSubjectId from the students field
updates = append(updates, firestore.Update{
Path: "students." + dataSubjectId,
Value: firestore.Delete,
})
// remove permission associated with dataSubjectId from the permissions field
updates = append(updates, firestore.Update{
Path: "permissions." + dataSubjectId,
Value: firestore.Delete,
})

// add swaps and surveys to nodesToTraverse
nodesToTraverse = append(nodesToTraverse, pal.Locator{
LocatorType: pal.Collection,
DataType: SwapDataType,
FirestoreLocator: pal.FirestoreLocator{
CollectionPath: []string{models.FirestoreCoursesCollection, models.FirestoreSwapsCollection},
DocIDs: []string{currentDbObjLocator.FirestoreLocator.DocIDs[0]},
Filters: []pal.Filter{
{
Path: "studentID",
Op: "==",
Value: dataSubjectId,
},
},
},
})
nodesToTraverse = append(nodesToTraverse, pal.Locator{
LocatorType: pal.Collection,
DataType: SurveyDataType,
FirestoreLocator: pal.FirestoreLocator{
CollectionPath: []string{models.FirestoreCoursesCollection, models.FirestoreSurveysCollection},
DocIDs: []string{currentDbObjLocator.FirestoreLocator.DocIDs[0]},
},
})

fieldsToUpdate = pal.FieldUpdates{
FirestoreUpdates: updates,
}
return
}
11 changes: 11 additions & 0 deletions backend/pkg/privacy/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package privacy

import "fmt"

var (
invalidLocatorDataType = fmt.Errorf("invalid locator data type")
)

func cannotCastFieldToType(field string, castType string) error {
return fmt.Errorf("cannot cast %s to %s", field, castType)
}
38 changes: 29 additions & 9 deletions backend/pkg/privacy/privacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,42 @@ const (
SwapDataType = "swap"
)

func HandleAccess(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) map[string]interface{} {
func HandleAccess(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (data map[string]interface{}, err error) {
switch currentDbObjLocator.DataType {
case UserDataType:
return accessUser(dataSubjectId, currentDbObjLocator, dbObj)
return handleAccessUser(dataSubjectId, currentDbObjLocator, dbObj)
case CourseDataType:
return accessCourse(dataSubjectId, currentDbObjLocator, dbObj)
return handleAccessCourse(dataSubjectId, currentDbObjLocator, dbObj)
case SectionDataType:
return accessSection(dataSubjectId, currentDbObjLocator, dbObj)
return handleAccessSection(dataSubjectId, currentDbObjLocator, dbObj)
case AssignmentDataType:
return accessAssignment(dataSubjectId, currentDbObjLocator, dbObj)
return handleAccessAssignment(dataSubjectId, currentDbObjLocator, dbObj)
case SurveyDataType:
return accessSurvey(dataSubjectId, currentDbObjLocator, dbObj)
return handleAccessSurvey(dataSubjectId, currentDbObjLocator, dbObj)
case SwapDataType:
return accessSwap(dataSubjectId, currentDbObjLocator, dbObj)
return handleAccessSwap(dataSubjectId, currentDbObjLocator, dbObj)
default:
// TODO: should return error
return nil
err = invalidLocatorDataType
return
}
}

func HandleDelete(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (nodesToTraverse []pal.Locator, deleteNode bool, fieldsToUpdate pal.FieldUpdates, err error) {
switch currentDbObjLocator.DataType {
case UserDataType:
return handleDeleteUser(dataSubjectId, currentDbObjLocator, dbObj)
case CourseDataType:
return handleDeleteCourse(dataSubjectId, currentDbObjLocator, dbObj)
case SectionDataType:
return handleDeleteSection(dataSubjectId, currentDbObjLocator, dbObj)
case AssignmentDataType:
return handleDeleteAssignment(dataSubjectId, currentDbObjLocator, dbObj)
case SurveyDataType:
return handleDeleteSurvey(dataSubjectId, currentDbObjLocator, dbObj)
case SwapDataType:
return handleDeleteSwap(dataSubjectId, currentDbObjLocator, dbObj)
default:
err = invalidLocatorDataType
return
}
}
81 changes: 78 additions & 3 deletions backend/pkg/privacy/section.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,90 @@
package privacy

import (
"fmt"

"cloud.google.com/go/firestore"
pal "github.com/privacy-pal/privacy-pal/go/pkg"
)

func accessSection(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) map[string]interface{} {
data := map[string]interface{}{
func handleAccessSection(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (data map[string]interface{}, err error) {
data = map[string]interface{}{
"startTime": dbObj["startTime"],
"endTime": dbObj["endTime"],
"location": dbObj["location"],
}

return data
return
}

func handleDeleteSection(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (nodesToTraverse []pal.Locator, deleteNode bool, fieldsToUpdate pal.FieldUpdates, err error) {
deleteNode = false

// decrement numEnrolled in course
updates := []firestore.Update{
{
Path: "numEnrolled",
Value: firestore.Increment(-1),
},
}

// remove dataSubjectId from swappedInStudents if exists
swappedInStudents, ok := dbObj["swappedInStudents"].(map[string]interface{})
if !ok {
err = cannotCastFieldToType("swappedInStudents", "map[string]interface{}")
return
}
for _, studentIDs := range swappedInStudents {
studentIDsSlice, ok := studentIDs.([]interface{})
if !ok {
err = cannotCastFieldToType(fmt.Sprintf("swappedInStudents entry %v", studentIDs), "[]interface{}")
return
}
for _, studentID := range studentIDsSlice {
id, ok := studentID.(string)
if !ok {
err = cannotCastFieldToType(fmt.Sprintf("swappedInStudents nested entry %v", studentID), "string")
return
}
if id == dataSubjectId {
updates = append(updates, firestore.Update{
Path: "swappedInStudents." + dataSubjectId,
Value: firestore.Delete,
})
}
}
}

// remove dataSubjectId from swappedOutStudents if exists
swappedOutStudents, ok := dbObj["swappedOutStudents"].(map[string]interface{})
if !ok {
err = cannotCastFieldToType("swappedOutStudents", "map[string]interface{}")
return
}
for _, studentIDs := range swappedOutStudents {
studentIDsSlice, ok := studentIDs.([]interface{})
if !ok {
err = cannotCastFieldToType(fmt.Sprintf("swappedOutStudents entry %v", studentIDs), "[]interface{}")
return
}
for _, studentID := range studentIDsSlice {
id, ok := studentID.(string)
if !ok {
err = cannotCastFieldToType(fmt.Sprintf("swappedOutStudents nested entry %v", studentID), "string")
return
}
if id == dataSubjectId {
updates = append(updates, firestore.Update{
Path: "swappedOutStudents." + dataSubjectId,
Value: firestore.Delete,
})
}
}
}

fieldsToUpdate = pal.FieldUpdates{
FirestoreUpdates: updates,
}

return
}
52 changes: 49 additions & 3 deletions backend/pkg/privacy/survey.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,63 @@
package privacy

import (
"fmt"

"cloud.google.com/go/firestore"
pal "github.com/privacy-pal/privacy-pal/go/pkg"
)

func accessSurvey(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) map[string]interface{} {
data := map[string]interface{}{
func handleAccessSurvey(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (data map[string]interface{}, err error) {
data = map[string]interface{}{
"name": dbObj["name"],
"description": dbObj["description"],
"endTime": dbObj["endTime"],
"options": dbObj["options"],
"responses": dbObj["responses"].(map[string]interface{})[dataSubjectId],
}

return data
return
}

func handleDeleteSurvey(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (nodesToTraverse []pal.Locator, deleteNode bool, fieldsToUpdate pal.FieldUpdates, err error) {
deleteNode = false

// remove responses[dataSubjectId] if exists
updates := []firestore.Update{
{
Path: "responses." + dataSubjectId,
Value: firestore.Delete,
},
}

// remove the result of dataSubjectId from each entry in results
results, ok := dbObj["results"].(map[string]interface{})
if ok { // result could be nil if no results
for option, data := range results {
courseUserData, ok := data.([]interface{})
if !ok {
err = fmt.Errorf("courseUserData is not a []interface{}")
return
}
for _, data := range courseUserData {
cud, ok := data.(map[string]interface{})
if !ok {
err = fmt.Errorf("cud is not a map[string]interface{}")
return
}
if cud["studentID"] == dataSubjectId {
updates = append(updates, firestore.Update{
Path: "results." + option,
Value: firestore.ArrayRemove(data),
})
}
}
}
}

fieldsToUpdate = pal.FieldUpdates{
FirestoreUpdates: updates,
}

return
}
11 changes: 8 additions & 3 deletions backend/pkg/privacy/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
pal "github.com/privacy-pal/privacy-pal/go/pkg"
)

func accessSwap(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) map[string]interface{} {
data := map[string]interface{}{
func handleAccessSwap(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (data map[string]interface{}, err error) {
data = map[string]interface{}{
"oldSectionID": dbObj["oldSectionID"],
"newSectionID": dbObj["newSectionID"],
"assignmentID": dbObj["assignmentID"],
Expand All @@ -16,5 +16,10 @@ func accessSwap(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal
"handledBy": dbObj["handledBy"],
}

return data
return
}

func handleDeleteSwap(dataSubjectId string, currentDbObjLocator pal.Locator, dbObj pal.DatabaseObject) (nodesToTraverse []pal.Locator, deleteNode bool, fieldsToUpdate pal.FieldUpdates, err error) {
deleteNode = true
return
}
Loading