From aeb356943b6f7a4142051632346106f98d3974f4 Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Wed, 26 Jun 2024 00:06:12 +0800 Subject: [PATCH 01/11] changed userId from uuid to googleId --- auth.go | 16 ++ database.go | 509 +++++++++++++++++++++++++++++++++------------- database_model.go | 30 ++- database_test.go | 377 ++++++++++++++++++---------------- main.go | 12 +- 5 files changed, 600 insertions(+), 344 deletions(-) diff --git a/auth.go b/auth.go index 1b4e1c5..d2b6af0 100644 --- a/auth.go +++ b/auth.go @@ -3,6 +3,7 @@ package main import ( "fmt" "html/template" + "log" "net/http" "github.com/gorilla/pat" @@ -35,6 +36,21 @@ func AuthHandler(router *pat.Router, config *Config) { fmt.Fprintln(res, err) return } + + // Extract user details from the goth.User + googleID := user.UserID + name := user.Name + email := user.Email + + // Example: Create or update a student with the extracted details + student := NewStudent(googleID, name, 18, 10.0, email, "91234567", "TE", "Mr. Smith", "Mrs. Doe") + err = createStudent(student.GoogleID, student) + if err != nil { + log.Println("Error creating student:", err) + } else { + log.Println("Student created/updated successfully!") + } + t, _ := template.ParseFiles("templates/success.html") t.Execute(res, user) }) diff --git a/database.go b/database.go index 8291abd..f154df2 100644 --- a/database.go +++ b/database.go @@ -3,12 +3,11 @@ package main import ( "context" "fmt" - "time" "log" "os" - // "github.com/joho/godotenv" + "github.com/joho/godotenv" firebase "firebase.google.com/go" "firebase.google.com/go/db" @@ -17,222 +16,446 @@ import ( // Use godot package to load/read the .env file and // return the value of the key -// func goDotEnvVariable(key string) string { +func goDotEnvVariable(key string) string { -// // load .env file -// err := godotenv.Load(".env") + // load .env file + err := godotenv.Load(".env") -// if err != nil { -// log.Fatalf("Error loading .env file") -// } + if err != nil { + log.Fatalf("Error loading .env file") + } -// return os.Getenv(key) -// } + return os.Getenv(key) +} -func database() { - // Find home directory. - // home, err := os.Getwd() - // if err != nil { - // return err - // } +// Initialize Firebase client +var firebaseClient *db.Client +// InitializeFirebase initializes the Firebase app and sets the global firebaseClient variable +func initializeFirebase() error { ctx := context.Background() - // configure database URL - // databaseURL := goDotEnvVariable("DATABASE_URL") - // if databaseURL == "" { - // return fmt.Errorf("DATABASE_URL is not set in the .env file") + // databaseURL, found := os.LookupEnv("DATABASE_URL") + // if !found { + // log.Fatalf("DATABASE_URL is not set in the environment variables") // } - databaseURL, found := os.LookupEnv("DATABASE_URL") - if !found { - log.Fatalf("DATABASE_URL is not set in the environment variables") - } + databaseURL := goDotEnvVariable("DATABASE_URL") conf := &firebase.Config{DatabaseURL: databaseURL} - // conf := &firebase.Config{ - // DatabaseURL: "https://edusync-test-default-rtdb.firebaseio.com/", - // } - - // Set up the Firebase app with the provided JSON file containing the service account key. - // opt := option.WithCredentialsFile(home + "edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json") - - // fetch service account key - // opt := option.WithCredentialsFile("edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json") - opt := option.WithCredentialsFile("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") - // opt := option.WithCredentialsFile("$HOME/secrets/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") + // opt := option.WithCredentialsFile("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") + opt := option.WithCredentialsFile("edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json") app, err := firebase.NewApp(ctx, conf, opt) if err != nil { - log.Fatalln("error in initializing firebase app: ", err) + return fmt.Errorf("error initializing firebase app: %v", err) } client, err := app.Database(ctx) if err != nil { - log.Fatalln("error in creating firebase DB client: ", err) + return fmt.Errorf("error creating firebase DB client: %v", err) } - // Student operations - student := NewStudent("Jane Doe", 7, 119.5, "jane_doe@nk.com", "91234567", "Tech Explorer", "Scott Smith", "Jackie Doe") - err = createStudent(client, student.ID.String(), student) - if err != nil { - log.Fatal(err) - } - fmt.Println("Student added/updated successfully!") + firebaseClient = client + return nil +} - readStudent, err := readStudent(client, student.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Student read successfully:", readStudent) +// func database() { +// // Find home directory. +// // home, err := os.Getwd() +// // if err != nil { +// // return err +// // } + +// ctx := context.Background() + +// // configure database URL +// // databaseURL := goDotEnvVariable("DATABASE_URL") +// // if databaseURL == "" { +// // return fmt.Errorf("DATABASE_URL is not set in the .env file") +// // } +// // databaseURL, found := os.LookupEnv("DATABASE_URL") +// // if !found { +// // log.Fatalf("DATABASE_URL is not set in the environment variables") +// // } +// // conf := &firebase.Config{DatabaseURL: databaseURL} + +// conf := &firebase.Config{ +// DatabaseURL: "https://edusync-test-default-rtdb.firebaseio.com/", +// } - studentUpdates := map[string]interface{}{ - "class": "Tech Explorer 2", - "updated_at": time.Now(), - } - err = updateStudent(client, student.ID.String(), studentUpdates) - if err != nil { - log.Fatal(err) - } - fmt.Println("Student updated successfully!") +// // Set up the Firebase app with the provided JSON file containing the service account key. +// // opt := option.WithCredentialsFile(home + "edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json") +// opt := option.WithCredentialsFile("edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json") +// // opt := option.WithCredentialsFile("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") +// // opt := option.WithCredentialsFile("$HOME/secrets/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") - err = deleteStudent(client, student.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Student deleted successfully!") +// app, err := firebase.NewApp(ctx, conf, opt) +// if err != nil { +// log.Fatalln("error in initializing firebase app: ", err) +// } - // Instructor operations - instructor := NewInstructor("Scott Smith", "123-456-7890", "scott@example.com", 50000.00, 10) - err = createInstructor(client, instructor.ID.String(), instructor) - if err != nil { - log.Fatal(err) - } - fmt.Println("Instructor added/updated successfully!") +// client, err := app.Database(ctx) +// if err != nil { +// log.Fatalln("error in creating firebase DB client: ", err) +// } - readInstructor, err := readInstructor(client, instructor.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Instructor read successfully:", readInstructor) +// // Student operations +// // student := NewStudent("Jane Doe", 7, 119.5, "jane_doe@nk.com", "91234567", "Tech Explorer", "Scott Smith", "Jackie Doe") +// // err = createStudent(client, student.ID.String(), student) +// googleIDStudent := "google-id-student" +// student := NewStudent(googleIDStudent, "Jane Doe", 7, 119.5, "jane_doe@nk.com", "91234567", "Tech Explorer", "Scott Smith", "Jackie Doe") +// err = createStudent(client, student.GoogleID, student) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Student added/updated successfully!") - instructorUpdates := map[string]interface{}{ - "base_pay": 55000.00, - "updated_at": time.Now(), - } - err = updateInstructor(client, instructor.ID.String(), instructorUpdates) - if err != nil { - log.Fatal(err) - } - fmt.Println("Instructor updated successfully!") +// // readStudent, err := readStudent(client, student.ID.String()) +// readStudent, err := readStudent(client, student.GoogleID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Student read successfully:", readStudent) - err = deleteInstructor(client, instructor.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Instructor deleted successfully!") +// studentUpdates := map[string]interface{}{ +// "class": "Tech Explorer 2", +// "updated_at": time.Now(), +// } +// // err = updateStudent(client, student.ID.String(), studentUpdates) +// err = updateStudent(client, student.GoogleID, studentUpdates) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Student updated successfully!") - // Parent operations - parent := NewParent("Jackie Doe", "jackjack@example.com", "98765432") - err = createParent(client, parent.ID.String(), parent) - if err != nil { - log.Fatal(err) - } - fmt.Println("Parent added/updated successfully!") +// // err = deleteStudent(client, student.ID.String()) +// err = deleteStudent(client, student.GoogleID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Student deleted successfully!") + +// // Instructor operations +// // instructor := NewInstructor("Scott Smith", "123-456-7890", "scott@example.com", 50000.00, 10) +// // err = createInstructor(client, instructor.ID.String(), instructor) +// googleIDInstructor := "google-id-instructor" +// instructor := NewInstructor(googleIDInstructor, "Scott Smith", "123-456-7890", "scott@example.com", 50000.00, 10) +// err = createInstructor(client, instructor.GoogleID, instructor) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Instructor added/updated successfully!") - readParent, err := readParent(client, parent.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Parent read successfully:", readParent) +// // readInstructor, err := readInstructor(client, instructor.ID.String()) +// readInstructor, err := readInstructor(client, instructor.GoogleID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Instructor read successfully:", readInstructor) - parentUpdates := map[string]interface{}{ - "email": "jackiejack@nk.com", - "updated_at": time.Now(), - } - err = updateParent(client, parent.ID.String(), parentUpdates) - if err != nil { - log.Fatal(err) - } - fmt.Println("Parent updated successfully!") +// instructorUpdates := map[string]interface{}{ +// "base_pay": 55000.00, +// "updated_at": time.Now(), +// } +// // err = updateInstructor(client, instructor.ID.String(), instructorUpdates) +// err = updateInstructor(client, instructor.GoogleID, instructorUpdates) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Instructor updated successfully!") - err = deleteParent(client, parent.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Parent deleted successfully!") -} +// // err = deleteInstructor(client, instructor.ID.String()) +// err = deleteInstructor(client, instructor.GoogleID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Instructor deleted successfully!") + +// // Parent operations +// // parent := NewParent("Jackie Doe", "jackjack@example.com", "98765432") +// // err = createParent(client, parent.ID.String(), parent) +// googleIDParent := "google-id-parent" +// parent := NewParent(googleIDParent, "Jackie Doe", "jackjack@example.com", "98765432") +// err = createParent(client, parent.GoogleID, parent) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Parent added/updated successfully!") + +// // readParent, err := readParent(client, parent.ID.String()) +// readParent, err := readParent(client, parent.GoogleID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Parent read successfully:", readParent) + +// parentUpdates := map[string]interface{}{ +// "email": "jackiejack@nk.com", +// "updated_at": time.Now(), +// } +// // err = updateParent(client, parent.ID.String(), parentUpdates) +// err = updateParent(client, parent.GoogleID, parentUpdates) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Parent updated successfully!") + +// // err = deleteParent(client, parent.ID.String()) +// err = deleteParent(client, parent.GoogleID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Parent deleted successfully!") +// } // Student CRUD -func createStudent(client *db.Client, userId string, student Student) error { - ref := client.NewRef("students/" + userId) +// func createStudent(client *db.Client, userId string, student Student) error { +// ref := client.NewRef("students/" + userId) +// return ref.Set(context.TODO(), student) +// } + +// func readStudent(client *db.Client, userId string) (Student, error) { +// ref := client.NewRef("students/" + userId) +// var student Student +// if err := ref.Get(context.TODO(), &student); err != nil { +// return Student{}, err +// } +// return student, nil +// } + +// func updateStudent(client *db.Client, userId string, updates map[string]interface{}) error { +// ref := client.NewRef("students/" + userId) +// return ref.Update(context.TODO(), updates) +// } + +// func deleteStudent(client *db.Client, userId string) error { +// ref := client.NewRef("students/" + userId) +// return ref.Delete(context.TODO()) +// } + +// // Student CRUD Ver 2 +// func createStudent(client *db.Client, googleID string, student Student) error { +// ref := client.NewRef("students/" + googleID) +// return ref.Set(context.TODO(), student) +// } + +// func readStudent(client *db.Client, googleID string) (Student, error) { +// ref := client.NewRef("students/" + googleID) +// var student Student +// if err := ref.Get(context.TODO(), &student); err != nil { +// return Student{}, err +// } +// return student, nil +// } + +// func updateStudent(client *db.Client, googleID string, updates map[string]interface{}) error { +// ref := client.NewRef("students/" + googleID) +// return ref.Update(context.TODO(), updates) +// } + +// func deleteStudent(client *db.Client, googleID string) error { +// ref := client.NewRef("students/" + googleID) +// return ref.Delete(context.TODO()) +// } + +// Student CRUD Ver 3 +func createStudent(googleID string, student Student) error { + ref := firebaseClient.NewRef("students/" + googleID) + if err := ref.Set(context.TODO(), student); err != nil { + return fmt.Errorf("error creating student: %v", err) + } return ref.Set(context.TODO(), student) } -func readStudent(client *db.Client, userId string) (Student, error) { - ref := client.NewRef("students/" + userId) +func readStudent(googleID string) (Student, error) { + ref := firebaseClient.NewRef("students/" + googleID) var student Student if err := ref.Get(context.TODO(), &student); err != nil { - return Student{}, err + return Student{}, fmt.Errorf("error reading student: %v", err) } return student, nil } -func updateStudent(client *db.Client, userId string, updates map[string]interface{}) error { - ref := client.NewRef("students/" + userId) +func updateStudent(googleID string, updates map[string]interface{}) error { + ref := firebaseClient.NewRef("students/" + googleID) + if err := ref.Update(context.TODO(), updates); err != nil { + return fmt.Errorf("error updating student: %v", err) + } return ref.Update(context.TODO(), updates) } -func deleteStudent(client *db.Client, userId string) error { - ref := client.NewRef("students/" + userId) +func deleteStudent(googleID string) error { + ref := firebaseClient.NewRef("students/" + googleID) + if err := ref.Delete(context.TODO()); err != nil { + return fmt.Errorf("error deleting student: %v", err) + } return ref.Delete(context.TODO()) } // Instructor CRUD -func createInstructor(client *db.Client, userId string, instructor Instructor) error { - ref := client.NewRef("instructors/" + userId) +// func createInstructor(client *db.Client, userId string, instructor Instructor) error { +// ref := client.NewRef("instructors/" + userId) +// return ref.Set(context.TODO(), instructor) +// } + +// func readInstructor(client *db.Client, userId string) (Instructor, error) { +// ref := client.NewRef("instructors/" + userId) +// var instructor Instructor +// if err := ref.Get(context.TODO(), &instructor); err != nil { +// return Instructor{}, err +// } +// return instructor, nil +// } + +// func updateInstructor(client *db.Client, userId string, updates map[string]interface{}) error { +// ref := client.NewRef("instructors/" + userId) +// return ref.Update(context.TODO(), updates) +// } + +// func deleteInstructor(client *db.Client, userId string) error { +// ref := client.NewRef("instructors/" + userId) +// return ref.Delete(context.TODO()) +// } + +// // Instructor CRUD Ver 2 +// func createInstructor(client *db.Client, googleID string, instructor Instructor) error { +// ref := client.NewRef("instructors/" + googleID) +// return ref.Set(context.TODO(), instructor) +// } + +// func readInstructor(client *db.Client, googleID string) (Instructor, error) { +// ref := client.NewRef("instructors/" + googleID) +// var instructor Instructor +// if err := ref.Get(context.TODO(), &instructor); err != nil { +// return Instructor{}, err +// } +// return instructor, nil +// } + +// func updateInstructor(client *db.Client, googleID string, updates map[string]interface{}) error { +// ref := client.NewRef("instructors/" + googleID) +// return ref.Update(context.TODO(), updates) +// } + +// func deleteInstructor(client *db.Client, googleID string) error { +// ref := client.NewRef("instructors/" + googleID) +// return ref.Delete(context.TODO()) +// } + +// Instructor CRUD Ver 3 +func createInstructor(googleID string, instructor Instructor) error { + ref := firebaseClient.NewRef("instructors/" + googleID) + if err := ref.Set(context.TODO(), instructor); err != nil { + return fmt.Errorf("error creating instructor: %v", err) + } return ref.Set(context.TODO(), instructor) } -func readInstructor(client *db.Client, userId string) (Instructor, error) { - ref := client.NewRef("instructors/" + userId) +func readInstructor(googleID string) (Instructor, error) { + ref := firebaseClient.NewRef("instructors/" + googleID) var instructor Instructor if err := ref.Get(context.TODO(), &instructor); err != nil { - return Instructor{}, err + return Instructor{}, fmt.Errorf("error reading instructor: %v", err) } return instructor, nil } -func updateInstructor(client *db.Client, userId string, updates map[string]interface{}) error { - ref := client.NewRef("instructors/" + userId) +func updateInstructor(googleID string, updates map[string]interface{}) error { + ref := firebaseClient.NewRef("instructors/" + googleID) + if err := ref.Update(context.TODO(), updates); err != nil { + return fmt.Errorf("error updating instructor: %v", err) + } return ref.Update(context.TODO(), updates) } -func deleteInstructor(client *db.Client, userId string) error { - ref := client.NewRef("instructors/" + userId) +func deleteInstructor(googleID string) error { + ref := firebaseClient.NewRef("instructors/" + googleID) + if err := ref.Delete(context.TODO()); err != nil { + return fmt.Errorf("error deleting instructor: %v", err) + } return ref.Delete(context.TODO()) } // Parent CRUD -func createParent(client *db.Client, userId string, parent Parent) error { - ref := client.NewRef("parents/" + userId) +// func createParent(client *db.Client, userId string, parent Parent) error { +// ref := client.NewRef("parents/" + userId) +// return ref.Set(context.TODO(), parent) +// } + +// func readParent(client *db.Client, userId string) (Parent, error) { +// ref := client.NewRef("parents/" + userId) +// var parent Parent +// if err := ref.Get(context.TODO(), &parent); err != nil { +// return Parent{}, err +// } +// return parent, nil +// } + +// func updateParent(client *db.Client, userId string, updates map[string]interface{}) error { +// ref := client.NewRef("parents/" + userId) +// return ref.Update(context.TODO(), updates) +// } + +// func deleteParent(client *db.Client, userId string) error { +// ref := client.NewRef("parents/" + userId) +// return ref.Delete(context.TODO()) +// } + +// // Parent CRUD Ver 2 +// func createParent(client *db.Client, googleID string, parent Parent) error { +// ref := client.NewRef("parents/" + googleID) +// return ref.Set(context.TODO(), parent) +// } + +// func readParent(client *db.Client, googleID string) (Parent, error) { +// ref := client.NewRef("parents/" + googleID) +// var parent Parent +// if err := ref.Get(context.TODO(), &parent); err != nil { +// return Parent{}, err +// } +// return parent, nil +// } + +// func updateParent(client *db.Client, googleID string, updates map[string]interface{}) error { +// ref := client.NewRef("parents/" + googleID) +// return ref.Update(context.TODO(), updates) +// } + +// func deleteParent(client *db.Client, googleID string) error { +// ref := client.NewRef("parents/" + googleID) +// return ref.Delete(context.TODO()) +// } + +// Parent CRUD Ver 3 +func createParent(googleID string, parent Parent) error { + ref := firebaseClient.NewRef("parents/" + googleID) + if err := ref.Set(context.TODO(), parent); err != nil { + return fmt.Errorf("error creating parent: %v", err) + } return ref.Set(context.TODO(), parent) } -func readParent(client *db.Client, userId string) (Parent, error) { - ref := client.NewRef("parents/" + userId) +func readParent(googleID string) (Parent, error) { + ref := firebaseClient.NewRef("parents/" + googleID) var parent Parent if err := ref.Get(context.TODO(), &parent); err != nil { - return Parent{}, err + return Parent{}, fmt.Errorf("error reading parent: %v", err) } return parent, nil } -func updateParent(client *db.Client, userId string, updates map[string]interface{}) error { - ref := client.NewRef("parents/" + userId) +func updateParent(googleID string, updates map[string]interface{}) error { + ref := firebaseClient.NewRef("parents/" + googleID) + if err := ref.Update(context.TODO(), updates); err != nil { + return fmt.Errorf("error updating parent: %v", err) + } return ref.Update(context.TODO(), updates) } -func deleteParent(client *db.Client, userId string) error { - ref := client.NewRef("parents/" + userId) +func deleteParent(googleID string) error { + ref := firebaseClient.NewRef("parents/" + googleID) + if err := ref.Delete(context.TODO()); err != nil { + return fmt.Errorf("error deleting parent: %v", err) + } return ref.Delete(context.TODO()) } diff --git a/database_model.go b/database_model.go index a8171d8..93a6b44 100644 --- a/database_model.go +++ b/database_model.go @@ -2,13 +2,13 @@ package main import ( "time" - - "github.com/google/uuid" + // "github.com/google/uuid" ) // Student struct for storing student information type Student struct { - ID uuid.UUID `json:"id"` + // ID uuid.UUID `json:"id"` + GoogleID string `json:"google_id"` Name string `json:"name"` Age int `json:"age"` LessonCredits float32 `json:"lesson_credits"` @@ -23,7 +23,8 @@ type Student struct { // Instructor struct for storing instructor information type Instructor struct { - ID uuid.UUID `json:"id"` + // ID uuid.UUID `json:"id"` + GoogleID string `json:"google_id"` Name string `json:"name"` ContactNumber string `json:"contact_number"` Email string `json:"email"` @@ -35,7 +36,8 @@ type Instructor struct { // Parent struct for storing parent information type Parent struct { - ID uuid.UUID `json:"id"` + // ID uuid.UUID `json:"id"` + GoogleID string `json:"google_id"` Name string `json:"name"` Email string `json:"email"` ContactNo string `json:"contact_no"` @@ -44,9 +46,11 @@ type Parent struct { } // NewStudent creates a new Student instance -func NewStudent(name string, age int, lessonCredits float32, email string, contactNumber string, class string, instructor string, parentName string) Student { +// func NewStudent(name string, age int, lessonCredits float32, email string, contactNumber string, class string, instructor string, parentName string) Student { +func NewStudent(googleID string, name string, age int, lessonCredits float32, email, contactNumber string, class string, instructor string, parentName string) Student { return Student{ - ID: uuid.New(), + // ID: uuid.New(), + GoogleID: googleID, Name: name, Age: age, LessonCredits: lessonCredits, @@ -61,9 +65,11 @@ func NewStudent(name string, age int, lessonCredits float32, email string, conta } // NewInstructor creates a new Instructor instance -func NewInstructor(name string, contactNumber string, email string, basePay float64, numberOfStudents int) Instructor { +// func NewInstructor(name string, contactNumber string, email string, basePay float64, numberOfStudents int) Instructor { +func NewInstructor(googleID, name, contactNumber, email string, basePay float64, numberOfStudents int) Instructor { return Instructor{ - ID: uuid.New(), + // ID: uuid.New(), + GoogleID: googleID, Name: name, ContactNumber: contactNumber, Email: email, @@ -74,9 +80,11 @@ func NewInstructor(name string, contactNumber string, email string, basePay floa } } -func NewParent(name string, email string, contactNo string) Parent { +// func NewParent(name string, email string, contactNo string) Parent { +func NewParent(googleID, name, email, contactNo string) Parent { return Parent{ - ID: uuid.New(), + // ID: uuid.New(), + GoogleID: googleID, Name: name, Email: email, ContactNo: contactNo, diff --git a/database_test.go b/database_test.go index ddd2578..21fec35 100644 --- a/database_test.go +++ b/database_test.go @@ -1,209 +1,226 @@ package main -import ( - "context" - "fmt" - "log" - "os" - "testing" - "time" - - firebase "firebase.google.com/go" - "google.golang.org/api/option" -) - -// Test using test database -// func TestDatabase(t *testing.T) { +// import ( +// "context" +// "fmt" +// "log" +// "testing" +// "time" + +// firebase "firebase.google.com/go" +// "google.golang.org/api/option" +// ) + +// // Test using test database +// // func TestDatabase(t *testing.T) { +// // ctx := context.Background() + +// // // configure database URL +// // conf := &firebase.Config{ +// // DatabaseURL: "https://edusync-test-default-rtdb.firebaseio.com/", +// // } + +// // // fetch service account key +// // opt := option.WithCredentialsFile("edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json") + +// // app, err := firebase.NewApp(ctx, conf, opt) +// // if err != nil { +// // t.Errorf("error in initializing firebase app: %v", err) +// // } + +// // client, err := app.Database(ctx) +// // if err != nil { +// // t.Errorf("error in creating firebase DB client: %v", err) +// // } + +// // // create ref at path students/:userId +// // ref := client.NewRef("students/" + fmt.Sprint(1)) + +// // // Test case 1: Successful set operation +// // data := map[string]interface{}{ +// // "name": "Jane Doe", +// // "age": "7", +// // "class": "Tech Explorer", +// // "instructor": "Scott Smith", +// // } +// // if err := ref.Set(ctx, data); err != nil { +// // t.Errorf("error in setting data: %v", err) +// // } + +// // // Test case 2: Get the set data +// // var getData map[string]interface{} +// // if err := ref.Get(ctx, &getData); err != nil { +// // t.Errorf("error in getting data: %v", err) +// // } +// // if getData["name"] != "Jane Doe" { +// // t.Errorf("expected name to be 'Jane Doe', got %v", getData["name"]) +// // } + +// // // Test case 3: Update the data +// // updateData := map[string]interface{}{ +// // "name": "John Doe", +// // } +// // if err := ref.Update(ctx, updateData); err != nil { +// // t.Errorf("error in updating data: %v", err) +// // } + +// // // Test case 4: Get the updated data +// // var updatedData map[string]interface{} +// // if err := ref.Get(ctx, &updatedData); err != nil { +// // t.Errorf("error in getting updated data: %v", err) +// // } +// // if updatedData["name"] != "John Doe" { +// // t.Errorf("expected name to be 'John Doe', got %v", updatedData["name"]) +// // } + +// // // Test case 5: Delete the data +// // if err := ref.Delete(ctx); err != nil { +// // t.Errorf("error in deleting data: %v", err) +// // } + +// // // Test case 6: Get the deleted data (should return an error) +// // var deletedData map[string]interface{} +// // // if err := ref.Get(ctx, &deletedData); err == nil { +// // // t.Errorf("expected error in getting deleted data, but got nil") +// // // } +// // if err := ref.Get(ctx, &deletedData); err == nil { +// // // If no error, check if the data is actually deleted +// // if deletedData != nil { +// // t.Errorf("Expected data to be deleted, but got %v", deletedData) +// // } +// // } else { +// // // Expecting an error, which indicates the data was not found +// // t.Logf("Received expected error after deletion: %v", err) +// // } +// // } + +// // Test using actual database +// func TestDatabaseCRUD(t *testing.T) { // ctx := context.Background() - -// // configure database URL -// conf := &firebase.Config{ -// DatabaseURL: "https://edusync-test-default-rtdb.firebaseio.com/", -// } - -// // fetch service account key -// opt := option.WithCredentialsFile("edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json") +// databaseURL := goDotEnvVariable("DATABASE_URL") +// // databaseURL, found := os.LookupEnv("DATABASE_URL") +// // if !found { +// // log.Fatalf("DATABASE_URL is not set in the environment variables") +// // } +// conf := &firebase.Config{DatabaseURL: databaseURL} +// opt := option.WithCredentialsFile("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") +// // opt := option.WithCredentialsFile("$HOME/secrets/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") // app, err := firebase.NewApp(ctx, conf, opt) // if err != nil { -// t.Errorf("error in initializing firebase app: %v", err) +// log.Fatalln("error in initializing firebase app: ", err) // } // client, err := app.Database(ctx) // if err != nil { -// t.Errorf("error in creating firebase DB client: %v", err) +// log.Fatalln("error in creating firebase DB client: ", err) // } -// // create ref at path students/:userId -// ref := client.NewRef("students/" + fmt.Sprint(1)) +// // Student operations +// // student := NewStudent("Jane Doe", 7, 119.5, "jane_doe@nk.com", "91234567", "Tech Explorer", "Scott Smith", "Jackie Doe") +// // err = createStudent(client, student.ID.String(), student) +// googleIDStudent := "google-id-student" +// student := NewStudent(googleIDStudent, "Jane Doe", 7, 119.5, "jane_doe@nk.com", "91234567", "Tech Explorer", "Scott Smith", "Jackie Doe") +// err = createStudent(client, student.GoogleID, student) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Student added/updated successfully!") -// // Test case 1: Successful set operation -// data := map[string]interface{}{ -// "name": "Jane Doe", -// "age": "7", -// "class": "Tech Explorer", -// "instructor": "Scott Smith", +// // readStudent, err := readStudent(client, student.ID.String()) +// readStudent, err := readStudent(client, student.GoogleID) +// if err != nil { +// log.Fatal(err) // } -// if err := ref.Set(ctx, data); err != nil { -// t.Errorf("error in setting data: %v", err) +// fmt.Println("Student read successfully:", readStudent) + +// studentUpdates := map[string]interface{}{ +// "class": "Tech Explorer 2", +// "updated_at": time.Now(), +// } +// // err = updateStudent(client, student.ID.String(), studentUpdates) +// err = updateStudent(client, student.GoogleID, studentUpdates) +// if err != nil { +// log.Fatal(err) // } +// fmt.Println("Student updated successfully!") -// // Test case 2: Get the set data -// var getData map[string]interface{} -// if err := ref.Get(ctx, &getData); err != nil { -// t.Errorf("error in getting data: %v", err) +// // err = deleteStudent(client, student.ID.String()) +// err = deleteStudent(client, student.GoogleID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Student deleted successfully!") + +// // Instructor operations +// // instructor := NewInstructor("Scott Smith", "123-456-7890", "scott@example.com", 50000.00, 10) +// // err = createInstructor(client, instructor.ID.String(), instructor) +// googleIDInstructor := "google-id-instructor" +// instructor := NewInstructor(googleIDInstructor, "Scott Smith", "123-456-7890", "scott@example.com", 50000.00, 10) +// err = createInstructor(client, instructor.GoogleID, instructor) +// if err != nil { +// log.Fatal(err) // } -// if getData["name"] != "Jane Doe" { -// t.Errorf("expected name to be 'Jane Doe', got %v", getData["name"]) +// fmt.Println("Instructor added/updated successfully!") + +// // readInstructor, err := readInstructor(client, instructor.ID.String()) +// readInstructor, err := readInstructor(client, instructor.GoogleID) +// if err != nil { +// log.Fatal(err) // } +// fmt.Println("Instructor read successfully:", readInstructor) -// // Test case 3: Update the data -// updateData := map[string]interface{}{ -// "name": "John Doe", +// instructorUpdates := map[string]interface{}{ +// "base_pay": 55000.00, +// "updated_at": time.Now(), // } -// if err := ref.Update(ctx, updateData); err != nil { -// t.Errorf("error in updating data: %v", err) +// // err = updateInstructor(client, instructor.ID.String(), instructorUpdates) +// err = updateInstructor(client, instructor.GoogleID, instructorUpdates) +// if err != nil { +// log.Fatal(err) // } +// fmt.Println("Instructor updated successfully!") -// // Test case 4: Get the updated data -// var updatedData map[string]interface{} -// if err := ref.Get(ctx, &updatedData); err != nil { -// t.Errorf("error in getting updated data: %v", err) +// // err = deleteInstructor(client, instructor.ID.String()) +// err = deleteInstructor(client, instructor.GoogleID) +// if err != nil { +// log.Fatal(err) // } -// if updatedData["name"] != "John Doe" { -// t.Errorf("expected name to be 'John Doe', got %v", updatedData["name"]) +// fmt.Println("Instructor deleted successfully!") + +// // Parent operations +// // parent := NewParent("Jackie Doe", "jackjack@example.com", "98765432") +// // err = createParent(client, parent.ID.String(), parent) +// googleIDParent := "google-id-parent" +// parent := NewParent(googleIDParent, "Jackie Doe", "jackjack@example.com", "98765432") +// err = createParent(client, parent.GoogleID, parent) +// if err != nil { +// log.Fatal(err) // } +// fmt.Println("Parent added/updated successfully!") -// // Test case 5: Delete the data -// if err := ref.Delete(ctx); err != nil { -// t.Errorf("error in deleting data: %v", err) +// // readParent, err := readParent(client, parent.ID.String()) +// readParent, err := readParent(client, parent.GoogleID) +// if err != nil { +// log.Fatal(err) // } +// fmt.Println("Parent read successfully:", readParent) -// // Test case 6: Get the deleted data (should return an error) -// var deletedData map[string]interface{} -// // if err := ref.Get(ctx, &deletedData); err == nil { -// // t.Errorf("expected error in getting deleted data, but got nil") -// // } -// if err := ref.Get(ctx, &deletedData); err == nil { -// // If no error, check if the data is actually deleted -// if deletedData != nil { -// t.Errorf("Expected data to be deleted, but got %v", deletedData) -// } -// } else { -// // Expecting an error, which indicates the data was not found -// t.Logf("Received expected error after deletion: %v", err) +// parentUpdates := map[string]interface{}{ +// "email": "jackiejack@nk.com", +// "updated_at": time.Now(), // } -// } +// // err = updateParent(client, parent.ID.String(), parentUpdates) +// err = updateParent(client, parent.GoogleID, parentUpdates) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Parent updated successfully!") -// Test using actual database -func TestDatabaseCRUD(t *testing.T) { - ctx := context.Background() - // databaseURL := goDotEnvVariable("DATABASE_URL") - databaseURL, found := os.LookupEnv("DATABASE_URL") - if !found { - log.Fatalf("DATABASE_URL is not set in the environment variables") - } - conf := &firebase.Config{DatabaseURL: databaseURL} - opt := option.WithCredentialsFile("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") - // opt := option.WithCredentialsFile("$HOME/secrets/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") - - app, err := firebase.NewApp(ctx, conf, opt) - if err != nil { - log.Fatalln("error in initializing firebase app: ", err) - } - - client, err := app.Database(ctx) - if err != nil { - log.Fatalln("error in creating firebase DB client: ", err) - } - - // Student operations - student := NewStudent("Jane Doe", 7, 119.5, "jane_doe@nk.com", "91234567", "Tech Explorer", "Scott Smith", "Jackie Doe") - err = createStudent(client, student.ID.String(), student) - if err != nil { - log.Fatal(err) - } - fmt.Println("Student added/updated successfully!") - - readStudent, err := readStudent(client, student.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Student read successfully:", readStudent) - - studentUpdates := map[string]interface{}{ - "class": "Tech Explorer 2", - "updated_at": time.Now(), - } - err = updateStudent(client, student.ID.String(), studentUpdates) - if err != nil { - log.Fatal(err) - } - fmt.Println("Student updated successfully!") - - err = deleteStudent(client, student.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Student deleted successfully!") - - // Instructor operations - instructor := NewInstructor("Scott Smith", "123-456-7890", "scott@example.com", 50000.00, 10) - err = createInstructor(client, instructor.ID.String(), instructor) - if err != nil { - log.Fatal(err) - } - fmt.Println("Instructor added/updated successfully!") - - readInstructor, err := readInstructor(client, instructor.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Instructor read successfully:", readInstructor) - - instructorUpdates := map[string]interface{}{ - "base_pay": 55000.00, - "updated_at": time.Now(), - } - err = updateInstructor(client, instructor.ID.String(), instructorUpdates) - if err != nil { - log.Fatal(err) - } - fmt.Println("Instructor updated successfully!") - - err = deleteInstructor(client, instructor.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Instructor deleted successfully!") - - // Parent operations - parent := NewParent("Jackie Doe", "jackjack@example.com", "98765432") - err = createParent(client, parent.ID.String(), parent) - if err != nil { - log.Fatal(err) - } - fmt.Println("Parent added/updated successfully!") - - readParent, err := readParent(client, parent.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Parent read successfully:", readParent) - - parentUpdates := map[string]interface{}{ - "email": "jackiejack@nk.com", - "updated_at": time.Now(), - } - err = updateParent(client, parent.ID.String(), parentUpdates) - if err != nil { - log.Fatal(err) - } - fmt.Println("Parent updated successfully!") - - err = deleteParent(client, parent.ID.String()) - if err != nil { - log.Fatal(err) - } - fmt.Println("Parent deleted successfully!") -} +// // err = deleteParent(client, parent.ID.String()) +// err = deleteParent(client, parent.GoogleID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Parent deleted successfully!") +// } diff --git a/main.go b/main.go index b80de92..724b111 100644 --- a/main.go +++ b/main.go @@ -8,16 +8,8 @@ import ( ) func init() { - // validateJSON("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") - // jsonFilePath := "$HOME/secrets/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json" - - // err := validateJSON(jsonFilePath) - // if err != nil { - // log.Fatalf("JSON validation failed: %v", err) - // } - - // log.Println("JSON is valid.") - database() + // database() + initializeFirebase() } func main() { From d7e814a5a6fb49ec9d95b982c368cbbdb6c10c2e Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Wed, 26 Jun 2024 21:51:45 +0800 Subject: [PATCH 02/11] Added role parameter to database --- auth.go | 2 +- database_model.go | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/auth.go b/auth.go index d2b6af0..0738bf3 100644 --- a/auth.go +++ b/auth.go @@ -43,7 +43,7 @@ func AuthHandler(router *pat.Router, config *Config) { email := user.Email // Example: Create or update a student with the extracted details - student := NewStudent(googleID, name, 18, 10.0, email, "91234567", "TE", "Mr. Smith", "Mrs. Doe") + student := NewStudent(googleID, name, 18, 10.0, email, "91234567", "TE", "Mr. Smith", "Mrs. Doe", "Student") err = createStudent(student.GoogleID, student) if err != nil { log.Println("Error creating student:", err) diff --git a/database_model.go b/database_model.go index 93a6b44..40eb5cf 100644 --- a/database_model.go +++ b/database_model.go @@ -17,6 +17,7 @@ type Student struct { Class string `json:"class"` Instructor string `json:"instructor"` ParentName string `json:"parent_name"` + Role string `json:"role"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } @@ -30,6 +31,7 @@ type Instructor struct { Email string `json:"email"` BasePay float64 `json:"base_pay"` NumberOfStudents int `json:"number_of_students"` + Role string `json:"role"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } @@ -41,13 +43,14 @@ type Parent struct { Name string `json:"name"` Email string `json:"email"` ContactNo string `json:"contact_no"` + Role string `json:"role"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // NewStudent creates a new Student instance // func NewStudent(name string, age int, lessonCredits float32, email string, contactNumber string, class string, instructor string, parentName string) Student { -func NewStudent(googleID string, name string, age int, lessonCredits float32, email, contactNumber string, class string, instructor string, parentName string) Student { +func NewStudent(googleID string, name string, age int, lessonCredits float32, email, contactNumber, class, instructor, parentName, role string) Student { return Student{ // ID: uuid.New(), GoogleID: googleID, @@ -59,6 +62,7 @@ func NewStudent(googleID string, name string, age int, lessonCredits float32, em Class: class, Instructor: instructor, ParentName: parentName, + Role: role, CreatedAt: time.Now(), UpdatedAt: time.Now(), } @@ -66,7 +70,7 @@ func NewStudent(googleID string, name string, age int, lessonCredits float32, em // NewInstructor creates a new Instructor instance // func NewInstructor(name string, contactNumber string, email string, basePay float64, numberOfStudents int) Instructor { -func NewInstructor(googleID, name, contactNumber, email string, basePay float64, numberOfStudents int) Instructor { +func NewInstructor(googleID, name, contactNumber, email, role string, basePay float64, numberOfStudents int) Instructor { return Instructor{ // ID: uuid.New(), GoogleID: googleID, @@ -75,19 +79,21 @@ func NewInstructor(googleID, name, contactNumber, email string, basePay float64, Email: email, BasePay: basePay, NumberOfStudents: numberOfStudents, + Role: role, CreatedAt: time.Now(), UpdatedAt: time.Now(), } } // func NewParent(name string, email string, contactNo string) Parent { -func NewParent(googleID, name, email, contactNo string) Parent { +func NewParent(googleID, name, email, contactNo, role string) Parent { return Parent{ // ID: uuid.New(), GoogleID: googleID, Name: name, Email: email, ContactNo: contactNo, + Role: role, CreatedAt: time.Now(), UpdatedAt: time.Now(), } From e2fb4cc04007cccad5393d1336adaef6e46efee5 Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Wed, 26 Jun 2024 21:53:42 +0800 Subject: [PATCH 03/11] fixed database testing, updated to google id --- database.go | 12 ++-- database_test.go | 142 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 4 deletions(-) diff --git a/database.go b/database.go index f154df2..cd53cb8 100644 --- a/database.go +++ b/database.go @@ -35,11 +35,15 @@ var firebaseClient *db.Client func initializeFirebase() error { ctx := context.Background() - // databaseURL, found := os.LookupEnv("DATABASE_URL") - // if !found { - // log.Fatalf("DATABASE_URL is not set in the environment variables") + databaseURL, found := os.LookupEnv("DATABASE_URL") + if !found { + log.Fatalf("DATABASE_URL is not set in the environment variables") + } + // databaseURL := goDotEnvVariable("DATABASE_URL") + // if databaseURL == "" { + // return fmt.Errorf("DATABASE_URL is not set in the environment variables") // } - databaseURL := goDotEnvVariable("DATABASE_URL") + conf := &firebase.Config{DatabaseURL: databaseURL} // opt := option.WithCredentialsFile("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") diff --git a/database_test.go b/database_test.go index 21fec35..4400306 100644 --- a/database_test.go +++ b/database_test.go @@ -1,5 +1,147 @@ package main +import ( + // "context" + // "fmt" + + // "os" + "reflect" + + // "strings" + "testing" + // firebase "firebase.google.com/go" + // "google.golang.org/api/option" +) + +func TestInitializeFirebase(t *testing.T) { + // Test case 1: FirebaseClient is set correctly + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + if firebaseClient == nil { + t.Fatal("FirebaseClient is not set") + } + + // Run tests + // os.Exit(t.Run()) +} + +// func initializeFirebaseWithApp(app *firebase.App) error { +// ctx := context.Background() + +// client, err := app.Database(ctx) +// if err != nil { +// return fmt.Errorf("error creating firebase DB client: %v", err) +// } + +// firebaseClient = client +// return nil +// } + +// Repeat the below test functions for Instructor and Parent entities +// Replace "Student" with "Instructor" and "student" with "instructor" in the test function names +// Replace "Student" with "Parent" and "student" with "parent" in the test function names +func TestCreateStudent(t *testing.T) { + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Create a new student + student := Student{ + GoogleID: "test-student", + Name: "John Doe", + Email: "johndoe@example.com", + Age: 12, + Class: "TE", + Instructor: "Awesomeness", + ParentName: "Jane Doe", + Role: "Student", + } + + err = createStudent(student.GoogleID, student) + if err != nil { + t.Fatalf("Error creating student: %v", err) + } + + // Read the created student + readStudent, err := readStudent(student.GoogleID) + if err != nil { + t.Fatalf("Error reading student: %v", err) + } + + // Assert that the created and read students are equal + if !reflect.DeepEqual(student, readStudent) { + t.Error("Created and read students are not equal") + } +} + +func TestReadStudent(t *testing.T) { + googleID := "test-student" + + student, err := readStudent(googleID) + if err != nil { + t.Fatalf("Failed to read student: %v", err) + } + + if student.GoogleID != googleID { + t.Fatalf("Expected GoogleID %v, got %v", googleID, student.GoogleID) + } +} + +func TestUpdateStudent(t *testing.T) { + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Update the student's email + updates := map[string]interface{}{ + "email": "johndoe@nk.com", + } + + err = updateStudent("test-student", updates) + if err != nil { + t.Fatalf("Error updating student: %v", err) + } + + // Read the updated student + readStudent, err := readStudent("test-student") + if err != nil { + t.Fatalf("Error reading student: %v", err) + } + + // Assert that the updated student's email is correct + if readStudent.Email != updates["email"] { + t.Errorf("Updated student's email is incorrect. Expected: %v, Got: %v", updates["email"], readStudent.Email) + } +} + +func TestDeleteStudent(t *testing.T) { + googleID := "test-student" + + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Delete the student + err = deleteStudent(googleID) + if err != nil { + t.Fatalf("Error deleting student: %v", err) + } + + // Try to read the deleted student + // _, err = readStudent(googleID) + // if err == nil { + // t.Error("Deleted student still exists") + // } +} + // import ( // "context" // "fmt" From 687062ae02adb22d7e4d5354c2d1aa8d1382734c Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Wed, 26 Jun 2024 23:14:16 +0800 Subject: [PATCH 04/11] removed original server code, placed in auth.go --- server.go | 99 -------------------------------------------------- server_test.go | 49 ------------------------- 2 files changed, 148 deletions(-) delete mode 100644 server.go delete mode 100644 server_test.go diff --git a/server.go b/server.go deleted file mode 100644 index fa76b58..0000000 --- a/server.go +++ /dev/null @@ -1,99 +0,0 @@ -package main - -import ( - "fmt" - "html/template" - "net/http" - "os" - "path/filepath" -) - -var homePages = map[string]string{ - "": "index.html", - "about": "about.html", - "contact": "contact.html", - "login": "login.html", -} - -var adminPages = map[string]string{ - "": "index.html", - "about": "about.html", -} - -var tmpl *template.Template -var adminTmpl *template.Template -var templateDir = "templates" - -func init() { - var err error - tmpl, err = template.ParseGlob(filepath.Join(templateDir, "*.html")) - if err != nil { - fmt.Println("Error parsing home templates: ", err) - os.Exit(1) - } - - adminTmpl, err = template.ParseGlob(filepath.Join(templateDir, "admin", "*.html")) - if err != nil { - fmt.Println("Error parsing admin templates: ", err) - os.Exit(1) - } -} - -func handler() http.Handler { - mux := http.NewServeMux() - mux.HandleFunc("/admin/", adminHandler) - mux.HandleFunc("/", mainHandler) - fmt.Println("Server started") - // http.ListenAndServe(":8080", mux) - // r.HandleFunc("/1", serverhome) - // r.HandleFunc("/2", setCookieHandler) - return mux -} - -func adminHandler(w http.ResponseWriter, r *http.Request) { - path := r.URL.Path[len("/admin/"):] - templateFile, ok := adminPages[path] - if !ok { - http.NotFound(w, r) - return - } - adminTmpl.ExecuteTemplate(w, templateFile, nil) -} - -func mainHandler(w http.ResponseWriter, r *http.Request) { - path := r.URL.Path[1:] - templateFile, ok := homePages[path] - if !ok { - http.NotFound(w, r) - return - } - tmpl.ExecuteTemplate(w, templateFile, nil) -} - -// func serverhome(w http.ResponseWriter, r *http.Request) { -// // w.Write([]byte("Hello World!")) -// fmt.Println(r) -// templates.ExecuteTemplate(w, "hello.html", nil) -// } - -// func setCookieHandler(w http.ResponseWriter, r *http.Request) { -// // Initialize a new cookie containing the string "Hello world!" and some -// // non-default attributes. -// cookie := http.Cookie{ -// Name: "exampleCookie", -// Value: "Hello world!", -// // Path: "/", -// // MaxAge: 3600, -// // HttpOnly: true, -// // Secure: true, -// // SameSite: http.SameSiteLaxMode, -// } - -// // Use the http.SetCookie() function to send the cookie to the client. -// // Behind the scenes this adds a `Set-Cookie` header to the response -// // containing the necessary cookie data. -// http.SetCookie(w, &cookie) - -// // Write a HTTP response as normal. -// w.Write([]byte("cookie set!")) -// } diff --git a/server_test.go b/server_test.go deleted file mode 100644 index 6acc6b0..0000000 --- a/server_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - "net/http/httptest" - "testing" -) - -func ahandler(w http.ResponseWriter, r *http.Request) { - - w.Write([]byte("Hello, World")) - -} - -func TestRouter(t *testing.T) { - - // req := httptest.NewRequest("GET", "http://192.168.1.129:8080/3", nil) - // req := httptest.NewRequest("GET", "http://127.0.0.1:8080/1", nil) - // w := httptest.NewRecorder() - - // ahandler(w, req) - - // resp := w.Result() - - // fmt.Println(resp.StatusCode) - req, err := http.NewRequest("GET", "/3", nil) - fmt.Println(req.Body) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := http.HandlerFunc(mainHandler) - - handler.ServeHTTP(rr, req) - // Check the status code is what we expect. - if status := rr.Code; status != http.StatusNotFound { - t.Errorf("handler returned wrong status code: got %v want %v", - status, http.StatusOK) - } - // Check the response body is what we expect. - // expected := "Hi" - // if rr.Body.String() != expected { - // t.Errorf("handler returned unexpected body: got %v want %v", - // rr.Body.String(), expected) - // } - -} From 7622679f4ce5021f05d408b35f5bea910198d438 Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Wed, 26 Jun 2024 23:14:42 +0800 Subject: [PATCH 05/11] standardising --- database_model.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/database_model.go b/database_model.go index 40eb5cf..dc8dca2 100644 --- a/database_model.go +++ b/database_model.go @@ -39,13 +39,13 @@ type Instructor struct { // Parent struct for storing parent information type Parent struct { // ID uuid.UUID `json:"id"` - GoogleID string `json:"google_id"` - Name string `json:"name"` - Email string `json:"email"` - ContactNo string `json:"contact_no"` - Role string `json:"role"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + GoogleID string `json:"google_id"` + Name string `json:"name"` + Email string `json:"email"` + ContactNumber string `json:"contact_no"` + Role string `json:"role"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } // NewStudent creates a new Student instance @@ -86,15 +86,15 @@ func NewInstructor(googleID, name, contactNumber, email, role string, basePay fl } // func NewParent(name string, email string, contactNo string) Parent { -func NewParent(googleID, name, email, contactNo, role string) Parent { +func NewParent(googleID, name, email, contactNumber, role string) Parent { return Parent{ // ID: uuid.New(), - GoogleID: googleID, - Name: name, - Email: email, - ContactNo: contactNo, - Role: role, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), + GoogleID: googleID, + Name: name, + Email: email, + ContactNumber: contactNumber, + Role: role, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), } } From 93ccbff2cbe9c43afddd2402710a5063aad02f89 Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Wed, 26 Jun 2024 23:37:35 +0800 Subject: [PATCH 06/11] Added admin model --- database_model.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/database_model.go b/database_model.go index dc8dca2..480f6de 100644 --- a/database_model.go +++ b/database_model.go @@ -36,6 +36,19 @@ type Instructor struct { UpdatedAt time.Time `json:"updated_at"` } +type Admin struct { + // ID uuid.UUID `json:"id"` + GoogleID string `json:"google_id"` + Name string `json:"name"` + ContactNumber string `json:"contact_number"` + Email string `json:"email"` + BasePay float64 `json:"base_pay"` + Incentive float64 `json:"incentive"` + Role string `json:"role"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + // Parent struct for storing parent information type Parent struct { // ID uuid.UUID `json:"id"` @@ -85,6 +98,21 @@ func NewInstructor(googleID, name, contactNumber, email, role string, basePay fl } } +func NewAdmin(googleID, name, contactNumber, email, role string, basePay, incentive float64) Admin { + return Admin{ + // ID: uuid.New(), + GoogleID: googleID, + Name: name, + ContactNumber: contactNumber, + Email: email, + BasePay: basePay, + Incentive: incentive, + Role: role, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } +} + // func NewParent(name string, email string, contactNo string) Parent { func NewParent(googleID, name, email, contactNumber, role string) Parent { return Parent{ From d83e128bb34bf541428d7ccb8df2fd336c596f93 Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Wed, 26 Jun 2024 23:48:57 +0800 Subject: [PATCH 07/11] reorganised database.go, added CRUD operations for admin --- database.go | 338 ++++++++++++++++++++++++++--------------------- database_test.go | 314 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 485 insertions(+), 167 deletions(-) diff --git a/database.go b/database.go index cd53cb8..2fbe1fa 100644 --- a/database.go +++ b/database.go @@ -63,6 +63,142 @@ func initializeFirebase() error { return nil } +// Student CRUD +func createStudent(googleID string, student Student) error { + ref := firebaseClient.NewRef("students/" + googleID) + if err := ref.Set(context.TODO(), student); err != nil { + return fmt.Errorf("error creating student: %v", err) + } + return ref.Set(context.TODO(), student) +} + +func readStudent(googleID string) (Student, error) { + ref := firebaseClient.NewRef("students/" + googleID) + var student Student + if err := ref.Get(context.TODO(), &student); err != nil { + return Student{}, fmt.Errorf("error reading student: %v", err) + } + return student, nil +} + +func updateStudent(googleID string, updates map[string]interface{}) error { + ref := firebaseClient.NewRef("students/" + googleID) + if err := ref.Update(context.TODO(), updates); err != nil { + return fmt.Errorf("error updating student: %v", err) + } + return ref.Update(context.TODO(), updates) +} + +func deleteStudent(googleID string) error { + ref := firebaseClient.NewRef("students/" + googleID) + if err := ref.Delete(context.TODO()); err != nil { + return fmt.Errorf("error deleting student: %v", err) + } + return ref.Delete(context.TODO()) +} + +// Instructor CRUD +func createInstructor(googleID string, instructor Instructor) error { + ref := firebaseClient.NewRef("instructors/" + googleID) + if err := ref.Set(context.TODO(), instructor); err != nil { + return fmt.Errorf("error creating instructor: %v", err) + } + return ref.Set(context.TODO(), instructor) +} + +func readInstructor(googleID string) (Instructor, error) { + ref := firebaseClient.NewRef("instructors/" + googleID) + var instructor Instructor + if err := ref.Get(context.TODO(), &instructor); err != nil { + return Instructor{}, fmt.Errorf("error reading instructor: %v", err) + } + return instructor, nil +} + +func updateInstructor(googleID string, updates map[string]interface{}) error { + ref := firebaseClient.NewRef("instructors/" + googleID) + if err := ref.Update(context.TODO(), updates); err != nil { + return fmt.Errorf("error updating instructor: %v", err) + } + return ref.Update(context.TODO(), updates) +} + +func deleteInstructor(googleID string) error { + ref := firebaseClient.NewRef("instructors/" + googleID) + if err := ref.Delete(context.TODO()); err != nil { + return fmt.Errorf("error deleting instructor: %v", err) + } + return ref.Delete(context.TODO()) +} + +// Admin CRUD +func createAdmin(googleID string, admin Admin) error { + ref := firebaseClient.NewRef("admins/" + googleID) + if err := ref.Set(context.TODO(), admin); err != nil { + return fmt.Errorf("error creating admin: %v", err) + } + return ref.Set(context.TODO(), admin) +} + +func readAdmin(googleID string) (Admin, error) { + ref := firebaseClient.NewRef("admins/" + googleID) + var admin Admin + if err := ref.Get(context.TODO(), &admin); err != nil { + return Admin{}, fmt.Errorf("error reading admin: %v", err) + } + return admin, nil +} + +func updateAdmin(googleID string, updates map[string]interface{}) error { + ref := firebaseClient.NewRef("admins/" + googleID) + if err := ref.Update(context.TODO(), updates); err != nil { + return fmt.Errorf("error updating admin: %v", err) + } + return ref.Update(context.TODO(), updates) +} + +func deleteAdmin(googleID string) error { + ref := firebaseClient.NewRef("admins/" + googleID) + if err := ref.Delete(context.TODO()); err != nil { + return fmt.Errorf("error deleting admin: %v", err) + } + return ref.Delete(context.TODO()) +} + +// Parent CRUD +func createParent(googleID string, parent Parent) error { + ref := firebaseClient.NewRef("parents/" + googleID) + if err := ref.Set(context.TODO(), parent); err != nil { + return fmt.Errorf("error creating parent: %v", err) + } + return ref.Set(context.TODO(), parent) +} + +func readParent(googleID string) (Parent, error) { + ref := firebaseClient.NewRef("parents/" + googleID) + var parent Parent + if err := ref.Get(context.TODO(), &parent); err != nil { + return Parent{}, fmt.Errorf("error reading parent: %v", err) + } + return parent, nil +} + +func updateParent(googleID string, updates map[string]interface{}) error { + ref := firebaseClient.NewRef("parents/" + googleID) + if err := ref.Update(context.TODO(), updates); err != nil { + return fmt.Errorf("error updating parent: %v", err) + } + return ref.Update(context.TODO(), updates) +} + +func deleteParent(googleID string) error { + ref := firebaseClient.NewRef("parents/" + googleID) + if err := ref.Delete(context.TODO()); err != nil { + return fmt.Errorf("error deleting parent: %v", err) + } + return ref.Delete(context.TODO()) +} + // func database() { // // Find home directory. // // home, err := os.Getwd() @@ -237,65 +373,6 @@ func initializeFirebase() error { // return ref.Delete(context.TODO()) // } -// // Student CRUD Ver 2 -// func createStudent(client *db.Client, googleID string, student Student) error { -// ref := client.NewRef("students/" + googleID) -// return ref.Set(context.TODO(), student) -// } - -// func readStudent(client *db.Client, googleID string) (Student, error) { -// ref := client.NewRef("students/" + googleID) -// var student Student -// if err := ref.Get(context.TODO(), &student); err != nil { -// return Student{}, err -// } -// return student, nil -// } - -// func updateStudent(client *db.Client, googleID string, updates map[string]interface{}) error { -// ref := client.NewRef("students/" + googleID) -// return ref.Update(context.TODO(), updates) -// } - -// func deleteStudent(client *db.Client, googleID string) error { -// ref := client.NewRef("students/" + googleID) -// return ref.Delete(context.TODO()) -// } - -// Student CRUD Ver 3 -func createStudent(googleID string, student Student) error { - ref := firebaseClient.NewRef("students/" + googleID) - if err := ref.Set(context.TODO(), student); err != nil { - return fmt.Errorf("error creating student: %v", err) - } - return ref.Set(context.TODO(), student) -} - -func readStudent(googleID string) (Student, error) { - ref := firebaseClient.NewRef("students/" + googleID) - var student Student - if err := ref.Get(context.TODO(), &student); err != nil { - return Student{}, fmt.Errorf("error reading student: %v", err) - } - return student, nil -} - -func updateStudent(googleID string, updates map[string]interface{}) error { - ref := firebaseClient.NewRef("students/" + googleID) - if err := ref.Update(context.TODO(), updates); err != nil { - return fmt.Errorf("error updating student: %v", err) - } - return ref.Update(context.TODO(), updates) -} - -func deleteStudent(googleID string) error { - ref := firebaseClient.NewRef("students/" + googleID) - if err := ref.Delete(context.TODO()); err != nil { - return fmt.Errorf("error deleting student: %v", err) - } - return ref.Delete(context.TODO()) -} - // Instructor CRUD // func createInstructor(client *db.Client, userId string, instructor Instructor) error { // ref := client.NewRef("instructors/" + userId) @@ -321,65 +398,6 @@ func deleteStudent(googleID string) error { // return ref.Delete(context.TODO()) // } -// // Instructor CRUD Ver 2 -// func createInstructor(client *db.Client, googleID string, instructor Instructor) error { -// ref := client.NewRef("instructors/" + googleID) -// return ref.Set(context.TODO(), instructor) -// } - -// func readInstructor(client *db.Client, googleID string) (Instructor, error) { -// ref := client.NewRef("instructors/" + googleID) -// var instructor Instructor -// if err := ref.Get(context.TODO(), &instructor); err != nil { -// return Instructor{}, err -// } -// return instructor, nil -// } - -// func updateInstructor(client *db.Client, googleID string, updates map[string]interface{}) error { -// ref := client.NewRef("instructors/" + googleID) -// return ref.Update(context.TODO(), updates) -// } - -// func deleteInstructor(client *db.Client, googleID string) error { -// ref := client.NewRef("instructors/" + googleID) -// return ref.Delete(context.TODO()) -// } - -// Instructor CRUD Ver 3 -func createInstructor(googleID string, instructor Instructor) error { - ref := firebaseClient.NewRef("instructors/" + googleID) - if err := ref.Set(context.TODO(), instructor); err != nil { - return fmt.Errorf("error creating instructor: %v", err) - } - return ref.Set(context.TODO(), instructor) -} - -func readInstructor(googleID string) (Instructor, error) { - ref := firebaseClient.NewRef("instructors/" + googleID) - var instructor Instructor - if err := ref.Get(context.TODO(), &instructor); err != nil { - return Instructor{}, fmt.Errorf("error reading instructor: %v", err) - } - return instructor, nil -} - -func updateInstructor(googleID string, updates map[string]interface{}) error { - ref := firebaseClient.NewRef("instructors/" + googleID) - if err := ref.Update(context.TODO(), updates); err != nil { - return fmt.Errorf("error updating instructor: %v", err) - } - return ref.Update(context.TODO(), updates) -} - -func deleteInstructor(googleID string) error { - ref := firebaseClient.NewRef("instructors/" + googleID) - if err := ref.Delete(context.TODO()); err != nil { - return fmt.Errorf("error deleting instructor: %v", err) - } - return ref.Delete(context.TODO()) -} - // Parent CRUD // func createParent(client *db.Client, userId string, parent Parent) error { // ref := client.NewRef("parents/" + userId) @@ -405,6 +423,56 @@ func deleteInstructor(googleID string) error { // return ref.Delete(context.TODO()) // } +// // Student CRUD Ver 2 +// func createStudent(client *db.Client, googleID string, student Student) error { +// ref := client.NewRef("students/" + googleID) +// return ref.Set(context.TODO(), student) +// } + +// func readStudent(client *db.Client, googleID string) (Student, error) { +// ref := client.NewRef("students/" + googleID) +// var student Student +// if err := ref.Get(context.TODO(), &student); err != nil { +// return Student{}, err +// } +// return student, nil +// } + +// func updateStudent(client *db.Client, googleID string, updates map[string]interface{}) error { +// ref := client.NewRef("students/" + googleID) +// return ref.Update(context.TODO(), updates) +// } + +// func deleteStudent(client *db.Client, googleID string) error { +// ref := client.NewRef("students/" + googleID) +// return ref.Delete(context.TODO()) +// } + +// // Instructor CRUD Ver 2 +// func createInstructor(client *db.Client, googleID string, instructor Instructor) error { +// ref := client.NewRef("instructors/" + googleID) +// return ref.Set(context.TODO(), instructor) +// } + +// func readInstructor(client *db.Client, googleID string) (Instructor, error) { +// ref := client.NewRef("instructors/" + googleID) +// var instructor Instructor +// if err := ref.Get(context.TODO(), &instructor); err != nil { +// return Instructor{}, err +// } +// return instructor, nil +// } + +// func updateInstructor(client *db.Client, googleID string, updates map[string]interface{}) error { +// ref := client.NewRef("instructors/" + googleID) +// return ref.Update(context.TODO(), updates) +// } + +// func deleteInstructor(client *db.Client, googleID string) error { +// ref := client.NewRef("instructors/" + googleID) +// return ref.Delete(context.TODO()) +// } + // // Parent CRUD Ver 2 // func createParent(client *db.Client, googleID string, parent Parent) error { // ref := client.NewRef("parents/" + googleID) @@ -429,37 +497,3 @@ func deleteInstructor(googleID string) error { // ref := client.NewRef("parents/" + googleID) // return ref.Delete(context.TODO()) // } - -// Parent CRUD Ver 3 -func createParent(googleID string, parent Parent) error { - ref := firebaseClient.NewRef("parents/" + googleID) - if err := ref.Set(context.TODO(), parent); err != nil { - return fmt.Errorf("error creating parent: %v", err) - } - return ref.Set(context.TODO(), parent) -} - -func readParent(googleID string) (Parent, error) { - ref := firebaseClient.NewRef("parents/" + googleID) - var parent Parent - if err := ref.Get(context.TODO(), &parent); err != nil { - return Parent{}, fmt.Errorf("error reading parent: %v", err) - } - return parent, nil -} - -func updateParent(googleID string, updates map[string]interface{}) error { - ref := firebaseClient.NewRef("parents/" + googleID) - if err := ref.Update(context.TODO(), updates); err != nil { - return fmt.Errorf("error updating parent: %v", err) - } - return ref.Update(context.TODO(), updates) -} - -func deleteParent(googleID string) error { - ref := firebaseClient.NewRef("parents/" + googleID) - if err := ref.Delete(context.TODO()); err != nil { - return fmt.Errorf("error deleting parent: %v", err) - } - return ref.Delete(context.TODO()) -} diff --git a/database_test.go b/database_test.go index 4400306..568852b 100644 --- a/database_test.go +++ b/database_test.go @@ -27,21 +27,7 @@ func TestInitializeFirebase(t *testing.T) { // os.Exit(t.Run()) } -// func initializeFirebaseWithApp(app *firebase.App) error { -// ctx := context.Background() - -// client, err := app.Database(ctx) -// if err != nil { -// return fmt.Errorf("error creating firebase DB client: %v", err) -// } - -// firebaseClient = client -// return nil -// } - -// Repeat the below test functions for Instructor and Parent entities -// Replace "Student" with "Instructor" and "student" with "instructor" in the test function names -// Replace "Student" with "Parent" and "student" with "parent" in the test function names +// Testing for student CRUD operations func TestCreateStudent(t *testing.T) { // Initialize Firebase client err := initializeFirebase() @@ -142,6 +128,304 @@ func TestDeleteStudent(t *testing.T) { // } } +// Testing for instructor CRUD operations +func TestCreateInstructor(t *testing.T) { + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Create a new instructor + instructor := Instructor{ + GoogleID: "test-instructor", + Name: "Awesomeness", + ContactNumber: "99999999", + Email: "awesome_instructor@nk.com", + BasePay: 15, + NumberOfStudents: 24, + Role: "Instructor", + } + + err = createInstructor(instructor.GoogleID, instructor) + if err != nil { + t.Fatalf("Error creating instructor: %v", err) + } + + // Read the created instructor + readInstructor, err := readInstructor(instructor.GoogleID) + if err != nil { + t.Fatalf("Error reading instructor: %v", err) + } + + // Assert that the created and read instructor are equal + if !reflect.DeepEqual(instructor, readInstructor) { + t.Error("Created and read instructors are not equal") + } +} + +func TestReadInstructor(t *testing.T) { + googleID := "test-instructor" + + instructor, err := readInstructor(googleID) + if err != nil { + t.Fatalf("Failed to read instructor: %v", err) + } + + if instructor.GoogleID != googleID { + t.Fatalf("Expected GoogleID %v, got %v", googleID, instructor.GoogleID) + } +} + +func TestUpdateInstructor(t *testing.T) { + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Update the instructor's email + updates := map[string]interface{}{ + "email": "amazing_instructor@nk.com", + } + + err = updateInstructor("test-instructor", updates) + if err != nil { + t.Fatalf("Error updating instructor: %v", err) + } + + // Read the updated instructor + readInstructor, err := readInstructor("test-instructor") + if err != nil { + t.Fatalf("Error reading instructor: %v", err) + } + + // Assert that the updated instructor's email is correct + if readInstructor.Email != updates["email"] { + t.Errorf("Updated instructor's email is incorrect. Expected: %v, Got: %v", updates["email"], readInstructor.Email) + } +} + +func TestDeleteInstructor(t *testing.T) { + googleID := "test-instructor" + + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Delete the instructor + err = deleteInstructor(googleID) + if err != nil { + t.Fatalf("Error deleting instructor: %v", err) + } + + // Try to read the deleted instructor + // _, err = readInstructor(googleID) + // if err == nil { + // t.Error("Deleted instructor still exists") + // } +} + +// Testing for admin CRUD operations +func TestCreateAdmin(t *testing.T) { + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Create a new admin + admin := Admin{ + GoogleID: "test-admin", + Name: "Awesomeness", + ContactNumber: "99999999", + Email: "awesome_admin@nk.com", + BasePay: 15, + Incentive: 24, + Role: "Admin", + } + + err = createAdmin(admin.GoogleID, admin) + if err != nil { + t.Fatalf("Error creating admin: %v", err) + } + + // Read the created admin + readAdmin, err := readAdmin(admin.GoogleID) + if err != nil { + t.Fatalf("Error reading admin: %v", err) + } + + // Assert that the created and read admin are equal + if !reflect.DeepEqual(admin, readAdmin) { + t.Error("Created and read admins are not equal") + } +} + +func TestReadAdmin(t *testing.T) { + googleID := "test-admin" + + admin, err := readAdmin(googleID) + if err != nil { + t.Fatalf("Failed to read instructor: %v", err) + } + + if admin.GoogleID != googleID { + t.Fatalf("Expected GoogleID %v, got %v", googleID, admin.GoogleID) + } +} + +func TestUpdateAdmin(t *testing.T) { + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Update the admin's email + updates := map[string]interface{}{ + "email": "amazing_admin@nk.com", + } + + err = updateAdmin("test-admin", updates) + if err != nil { + t.Fatalf("Error updating admin: %v", err) + } + + // Read the updated admin + readAdmin, err := readAdmin("test-admin") + if err != nil { + t.Fatalf("Error reading admin: %v", err) + } + + // Assert that the updated admin's email is correct + if readAdmin.Email != updates["email"] { + t.Errorf("Updated admin's email is incorrect. Expected: %v, Got: %v", updates["email"], readAdmin.Email) + } +} + +func TestDeleteAdmin(t *testing.T) { + googleID := "test-admin" + + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Delete the admin + err = deleteAdmin(googleID) + if err != nil { + t.Fatalf("Error deleting admin: %v", err) + } + + // Try to read the deleted admin + // _, err = readAdmin(googleID) + // if err == nil { + // t.Error("Deleted admin still exists") + // } +} + +// Testing for parent CRUD operations +func TestCreateParent(t *testing.T) { + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Create a new parent + parent := Parent{ + GoogleID: "test-parent", + Name: "Awesomeness", + ContactNumber: "99999999", + Email: "janedoe@nk.com", + Role: "Parent", + } + + err = createParent(parent.GoogleID, parent) + if err != nil { + t.Fatalf("Error creating parent: %v", err) + } + + // Read the created parent + readParent, err := readParent(parent.GoogleID) + if err != nil { + t.Fatalf("Error reading parent: %v", err) + } + + // Assert that the created and read parent are equal + if !reflect.DeepEqual(parent, readParent) { + t.Error("Created and read parents are not equal") + } +} + +func TestReadParent(t *testing.T) { + googleID := "test-parent" + + parent, err := readParent(googleID) + if err != nil { + t.Fatalf("Failed to read parent: %v", err) + } + + if parent.GoogleID != googleID { + t.Fatalf("Expected GoogleID %v, got %v", googleID, parent.GoogleID) + } +} + +func TestUpdateParent(t *testing.T) { + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Update the parent's email + updates := map[string]interface{}{ + "email": "janedoe_parent@nk.com", + } + + err = updateParent("test-parent", updates) + if err != nil { + t.Fatalf("Error updating parent: %v", err) + } + + // Read the updated parent + readParent, err := readParent("test-parent") + if err != nil { + t.Fatalf("Error reading parent: %v", err) + } + + // Assert that the updated parent's email is correct + if readParent.Email != updates["email"] { + t.Errorf("Updated parent's email is incorrect. Expected: %v, Got: %v", updates["email"], readParent.Email) + } +} + +func TestDeleteParent(t *testing.T) { + googleID := "test-parent" + + // Initialize Firebase client + err := initializeFirebase() + if err != nil { + t.Fatalf("Error initializing Firebase: %v", err) + } + + // Delete the parent + err = deleteInstructor(googleID) + if err != nil { + t.Fatalf("Error deleting parent: %v", err) + } + + // Try to read the deleted parent + // _, err = readParent(googleID) + // if err == nil { + // t.Error("Deleted parent still exists") + // } +} + // import ( // "context" // "fmt" From 0803dc643e967efa67d76b5c5c23069692e53b8d Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Thu, 27 Jun 2024 00:01:11 +0800 Subject: [PATCH 08/11] commented unneeded code --- database.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/database.go b/database.go index 2fbe1fa..fc4c2ec 100644 --- a/database.go +++ b/database.go @@ -7,7 +7,7 @@ import ( "log" "os" - "github.com/joho/godotenv" + // "github.com/joho/godotenv" firebase "firebase.google.com/go" "firebase.google.com/go/db" @@ -15,18 +15,18 @@ import ( ) // Use godot package to load/read the .env file and -// return the value of the key -func goDotEnvVariable(key string) string { +// return the value of the key (for local env) +// func goDotEnvVariable(key string) string { - // load .env file - err := godotenv.Load(".env") +// // load .env file +// err := godotenv.Load(".env") - if err != nil { - log.Fatalf("Error loading .env file") - } +// if err != nil { +// log.Fatalf("Error loading .env file") +// } - return os.Getenv(key) -} +// return os.Getenv(key) +// } // Initialize Firebase client var firebaseClient *db.Client From 8cf804ef1786a80b34455fb3e29576dd91a99719 Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Thu, 27 Jun 2024 00:13:48 +0800 Subject: [PATCH 09/11] Trying to fix conflict issues --- auth.go | 66 ------------------------------ authHandler.go | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 16 +++----- 3 files changed, 115 insertions(+), 76 deletions(-) delete mode 100644 auth.go create mode 100644 authHandler.go diff --git a/auth.go b/auth.go deleted file mode 100644 index 0738bf3..0000000 --- a/auth.go +++ /dev/null @@ -1,66 +0,0 @@ -package main - -import ( - "fmt" - "html/template" - "log" - "net/http" - - "github.com/gorilla/pat" - "github.com/gorilla/sessions" - "github.com/markbates/goth" - "github.com/markbates/goth/gothic" - "github.com/markbates/goth/providers/google" -) - -// AuthHandler sets up the authentication routes on the provided router -func AuthHandler(router *pat.Router, config *Config) { - maxAge := 86400 * 30 // 30 days - isProd := true // Set to true when serving over https - - store := sessions.NewCookieStore([]byte(config.SessionSecret)) - store.MaxAge(maxAge) - store.Options.Path = "/" - store.Options.HttpOnly = true // HttpOnly should always be enabled - store.Options.Secure = isProd - - gothic.Store = store - - goth.UseProviders( - google.New(config.GoogleClientID, config.GoogleClientSecret, "https://localhost:8080/auth/google/callback", "email", "profile"), - ) - - router.Get("/auth/{provider}/callback", func(res http.ResponseWriter, req *http.Request) { - user, err := gothic.CompleteUserAuth(res, req) - if err != nil { - fmt.Fprintln(res, err) - return - } - - // Extract user details from the goth.User - googleID := user.UserID - name := user.Name - email := user.Email - - // Example: Create or update a student with the extracted details - student := NewStudent(googleID, name, 18, 10.0, email, "91234567", "TE", "Mr. Smith", "Mrs. Doe", "Student") - err = createStudent(student.GoogleID, student) - if err != nil { - log.Println("Error creating student:", err) - } else { - log.Println("Student created/updated successfully!") - } - - t, _ := template.ParseFiles("templates/success.html") - t.Execute(res, user) - }) - - router.Get("/auth/{provider}", func(res http.ResponseWriter, req *http.Request) { - gothic.BeginAuthHandler(res, req) - }) - - router.Get("/", func(res http.ResponseWriter, req *http.Request) { - t, _ := template.ParseFiles("templates/index.html") - t.Execute(res, false) - }) -} diff --git a/authHandler.go b/authHandler.go new file mode 100644 index 0000000..ed4db95 --- /dev/null +++ b/authHandler.go @@ -0,0 +1,109 @@ +package main + +import ( + "fmt" + "html/template" + "net/http" + + "github.com/gorilla/mux" + "github.com/gorilla/sessions" + "github.com/markbates/goth" + "github.com/markbates/goth/gothic" + "github.com/markbates/goth/providers/google" +) + +// AuthHandler sets up the authentication routes on the provided router +// func AuthHandler(router *pat.Router, config *Config) { +// maxAge := 86400 * 30 // 30 days +// isProd := true // Set to true when serving over https + +// store := sessions.NewCookieStore([]byte(config.SessionSecret)) +// store.MaxAge(maxAge) +// store.Options.Path = "/" +// store.Options.HttpOnly = true // HttpOnly should always be enabled +// store.Options.Secure = isProd + +// gothic.Store = store + +// goth.UseProviders( +// google.New(config.GoogleClientID, config.GoogleClientSecret, "https://localhost:8080/auth/google/callback", "email", "profile"), +// ) + +// router.Get("/auth/{provider}/callback", func(res http.ResponseWriter, req *http.Request) { +// user, err := gothic.CompleteUserAuth(res, req) +// if err != nil { +// fmt.Fprintln(res, err) +// return +// } + +// // // Extract user details from the goth.User +// // googleID := user.UserID +// // name := user.Name +// // email := user.Email + +// // // Example: Create or update a student with the extracted details +// // student := NewStudent(googleID, name, 18, 10.0, email, "91234567", "TE", "Mr. Smith", "Mrs. Doe", "Student") +// // err = createStudent(student.GoogleID, student) +// // if err != nil { +// // log.Println("Error creating student:", err) +// // } else { +// // log.Println("Student created/updated successfully!") +// // } + +// t, _ := template.ParseFiles("templates/success.html") +// t.Execute(res, user) +// }) + +// router.Get("/auth/{provider}", func(res http.ResponseWriter, req *http.Request) { +// gothic.BeginAuthHandler(res, req) +// }) + +// router.Get("/", func(res http.ResponseWriter, req *http.Request) { +// t, _ := template.ParseFiles("templates/index.html") +// t.Execute(res, false) +// }) +// } + +func AuthHandler(router *mux.Router, config *Config) { + maxAge := 86400 * 30 // 30 days + isProd := true // Set to true when serving over https + + store := sessions.NewCookieStore([]byte(config.SessionSecret)) + store.MaxAge(maxAge) + store.Options.Path = "/" + store.Options.HttpOnly = true // HttpOnly should always be enabled + store.Options.Secure = isProd + + gothic.Store = store + + goth.UseProviders( + google.New(config.GoogleClientID, config.GoogleClientSecret, "https://localhost:8080/auth/google/callback", "email", "profile"), + ) + + router.HandleFunc("/auth/{provider}/callback", func(res http.ResponseWriter, req *http.Request) { + user, err := gothic.CompleteUserAuth(res, req) + if err != nil { + fmt.Fprintln(res, err) + return + } + t, err := template.ParseFiles("templates/success.html") + if err != nil { + http.Error(res, err.Error(), http.StatusInternalServerError) + return + } + t.Execute(res, user) + }).Methods("GET") + + router.HandleFunc("/auth/{provider}", func(res http.ResponseWriter, req *http.Request) { + gothic.BeginAuthHandler(res, req) + }).Methods("GET") + + router.HandleFunc("/login", func(res http.ResponseWriter, req *http.Request) { + t, err := template.ParseFiles("templates/login.html") + if err != nil { + http.Error(res, err.Error(), http.StatusInternalServerError) + return + } + t.Execute(res, false) + }).Methods("GET") +} diff --git a/main.go b/main.go index 724b111..98a56da 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,7 @@ import ( "log" "net/http" - "github.com/gorilla/pat" + "github.com/gorilla/mux" ) func init() { @@ -13,21 +13,17 @@ func init() { } func main() { - // http.HandleFunc("/1", serverhome) - // http.HandleFunc("/2", setCookieHandler) - // http.ListenAndServe(":8080", handler()) - // http.ListenAndServeTLS("192.168.1.129:8080", "server.crt", "server.key", handler()) - - // err := http.ListenAndServeTLS(":8080", "server.crt", "server.key", handler()) - // Load configuration config, err := LoadConfig("config.json") if err != nil { log.Fatalf("could not load config: %v", err) } - // Create a new router - router := pat.New() + router := mux.NewRouter() + + // Serving static files + fs := http.FileServer(http.Dir("assets")) + router.PathPrefix("/assets").Handler(http.StripPrefix("/assets", fs)) // Set up authentication routes AuthHandler(router, config) From a39d4bd0080f228a8806959f200189e6940a0068 Mon Sep 17 00:00:00 2001 From: Jiawei <119054683+APandamonium1@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:19:13 +0800 Subject: [PATCH 10/11] Delete config.json --- config.json | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 config.json diff --git a/config.json b/config.json deleted file mode 100644 index 6016a33..0000000 --- a/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "session_secret":"Secret-session-key", - "google_client_id":"8283214538-lr39n0mnn0el6p51tb4jk80i7k3ima9q.apps.googleusercontent.com", - "google_client_secret":"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" -} \ No newline at end of file From a852f168a745f1f296c861ecfdfaaf2e271de1bb Mon Sep 17 00:00:00 2001 From: PandaJW <5168pandayoyo@gmail.com> Date: Thu, 27 Jun 2024 00:26:27 +0800 Subject: [PATCH 11/11] forgot to change firebase json --- database.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database.go b/database.go index fc4c2ec..deda998 100644 --- a/database.go +++ b/database.go @@ -46,8 +46,8 @@ func initializeFirebase() error { conf := &firebase.Config{DatabaseURL: databaseURL} - // opt := option.WithCredentialsFile("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") - opt := option.WithCredentialsFile("edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json") + opt := option.WithCredentialsFile("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") + // opt := option.WithCredentialsFile("edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json") app, err := firebase.NewApp(ctx, conf, opt) if err != nil {