diff --git a/.github/workflows/example.yml b/.github/workflows/example.yml index 3dfe300..f070ce3 100644 --- a/.github/workflows/example.yml +++ b/.github/workflows/example.yml @@ -5,6 +5,10 @@ on: pull_request: branches: [main] +env: + DATABASE_URL: ${{secrets.DATABASE_URL}} + # FIREBASE_ADMIN_PASSPHRASE: ${{secrets.FIREBASE_ADMIN_PASSPHRASE}} + jobs: example: name: Create Ubuntu OS @@ -27,6 +31,26 @@ jobs: go mod tidy go get github.com/franela/goblin ls + + # - name: Setup Firebase JSON file + # run: echo "{${{ secrets.FIREBASE_JSON }}}" > edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json + + # - name: Build and run JSON validator + # run: | + # go run json_validator.go edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json + + - name: Decrypt Firebase JSON + run: | + chmod +x decrypt_secret.sh + ./decrypt_secret.sh + env: + FIREBASE_ADMIN_PASSPHRASE: ${{secrets.FIREBASE_ADMIN_PASSPHRASE}} + + - name: Testing, to be removed + run: | + ls + # cat $HOME/secrets/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json + cat edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json - name: Go Test run: | @@ -36,30 +60,30 @@ jobs: name: Success Message (Discord) uses: discord-actions/message@v2 with: - webhookUrl: https://discord.com/api/webhooks/1237964301201965127/ZYe3gYTeweYEfA_Q0I-JWFVXA2dVMp7Pw7jeNNd2UlFCtvIS8ZvIN_CRQ-gUwSgl7eD2 + webhookUrl: ${{secrets.DISCORD_WEBHOOK}} message: SUCCESSFULLLL in branch ${{github.ref}} by ${{github.actor}} - if: ${{success()}} name: Success Message (Telegram) uses: akeylimepie/telegram-action@v0.1.2 with: - token: 6795256205:AAHm19-9zOM4jMtEtVOSDGExXAtg5J67rKc - chat_id: -4244340354 + token: ${{secrets.TELEGRAM_TOKEN}} + chat_id: ${{secrets.TELEGRAM_CHAT_ID}} text: SUCCESSFULLLL in branch ${{github.ref}} by ${{github.actor}} - if: ${{failure()}} name: Failure Message (Discord) uses: discord-actions/message@v2 with: - webhookUrl: https://discord.com/api/webhooks/1237964301201965127/ZYe3gYTeweYEfA_Q0I-JWFVXA2dVMp7Pw7jeNNd2UlFCtvIS8ZvIN_CRQ-gUwSgl7eD2 + webhookUrl: ${{secrets.DISCORD_WEBHOOK}} message: FAILUREEEE in branch ${{github.ref}} by ${{github.actor}} - if: ${{failure()}} name: Failure Message (Telegram) uses: akeylimepie/telegram-action@v0.1.2 with: - token: 6795256205:AAHm19-9zOM4jMtEtVOSDGExXAtg5J67rKc - chat_id: -4244340354 + token: ${{secrets.TELEGRAM_TOKEN}} + chat_id: ${{secrets.TELEGRAM_CHAT_ID}} text: FAILUREEEE in branch ${{github.ref}} by ${{github.actor}} #- name: Setup Python diff --git a/.gitignore b/.gitignore index d35e446..eba6e38 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ *.crt *.key *.pem -edusync-firebase.json +edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json +edusync-test-firebase-adminsdk-hk5kl-9af0162b09.json .env \ No newline at end of file diff --git a/EduSync.exe b/EduSync.exe index e96e90d..5fc2ae0 100644 Binary files a/EduSync.exe and b/EduSync.exe differ diff --git a/database.go b/database.go index 77cfac7..8291abd 100644 --- a/database.go +++ b/database.go @@ -3,117 +3,236 @@ 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" "google.golang.org/api/option" ) -// use godot package to load/read the .env file and +// 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") +// } + +// return os.Getenv(key) +// } + +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/", + // } + + // 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") + + app, err := firebase.NewApp(ctx, conf, opt) if err != nil { - log.Fatalf("Error loading .env file") + log.Fatalln("error in initializing firebase app: ", err) } - return os.Getenv(key) -} + client, err := app.Database(ctx) + if err != nil { + log.Fatalln("error in creating firebase DB client: ", err) + } -type FireDB struct { - *db.Client -} + // 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!") -var fireDB FireDB + readStudent, err := readStudent(client, student.ID.String()) + if err != nil { + log.Fatal(err) + } + fmt.Println("Student read successfully:", readStudent) -// Connect initializes and connects to the Firebase Realtime Database. -// It uses the provided JSON file containing the service account key to authenticate with Firebase. -// The DatabaseURL is set to the Firebase project's Realtime Database URL. -// The function returns an error if any step fails during the initialization or connection process. -func (db *FireDB) Connect() error { - // Find home directory. - home, err := os.Getwd() + studentUpdates := map[string]interface{}{ + "class": "Tech Explorer 2", + "updated_at": time.Now(), + } + err = updateStudent(client, student.ID.String(), studentUpdates) if err != nil { - return err + log.Fatal(err) } + fmt.Println("Student updated successfully!") - // Create a context for the Firebase app. - ctx := context.Background() + err = deleteStudent(client, student.ID.String()) + if err != nil { + log.Fatal(err) + } + fmt.Println("Student deleted successfully!") - // Set up the Firebase app with the provided JSON file containing the service account key. - opt := option.WithCredentialsFile(home + "edusync-firebase.json") - dotenv := goDotEnvVariable("DATABASE_URL") - config := &firebase.Config{DatabaseURL: dotenv} + // 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!") - app, err := firebase.NewApp(ctx, config, opt) - // opt := option.WithCredentialsFile("edusync-firebase.json") - // app, err := firebase.NewApp(context.Background(), nil, opt) + readInstructor, err := readInstructor(client, instructor.ID.String()) if err != nil { - return fmt.Errorf("error initializing app: %v", err) + log.Fatal(err) } + fmt.Println("Instructor read successfully:", readInstructor) - // Initialize the Firebase Realtime Database client. - client, err := app.Database(ctx) + instructorUpdates := map[string]interface{}{ + "base_pay": 55000.00, + "updated_at": time.Now(), + } + err = updateInstructor(client, instructor.ID.String(), instructorUpdates) if err != nil { - return fmt.Errorf("error initializing database: %v", err) + log.Fatal(err) } + fmt.Println("Instructor updated successfully!") - // Assign the Firebase Realtime Database client to the FireDB struct. - db.Client = client - return nil -} + err = deleteInstructor(client, instructor.ID.String()) + if err != nil { + log.Fatal(err) + } + fmt.Println("Instructor deleted successfully!") -func FirebaseDB() *FireDB { - return &fireDB -} + // 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!") -func connectToFirebase() error { - fireDB := FirebaseDB() - err := fireDB.Connect() + readParent, err := readParent(client, parent.ID.String()) if err != nil { - return err + log.Fatal(err) } + fmt.Println("Parent read successfully:", readParent) - ref := fireDB.NewRef("/") - err = ref.Set(context.Background(), map[string]string{ - "name": "Jane Doe", - "age": "7", - "class": "Tech Explorer", - "instructor": "Scott Smith", - }) + parentUpdates := map[string]interface{}{ + "email": "jackiejack@nk.com", + "updated_at": time.Now(), + } + err = updateParent(client, parent.ID.String(), parentUpdates) if err != nil { - return err + log.Fatal(err) } - return nil + fmt.Println("Parent updated successfully!") + + err = deleteParent(client, parent.ID.String()) + if err != nil { + log.Fatal(err) + } + fmt.Println("Parent deleted successfully!") } -// CRUD operations -func (db *FireDB) Create(refPath string, data interface{}) error { - ref := db.NewRef(refPath) - return ref.Set(context.Background(), data) +// Student CRUD +func createStudent(client *db.Client, userId string, student Student) error { + ref := client.NewRef("students/" + userId) + return ref.Set(context.TODO(), student) } -func (db *FireDB) Read(refPath string, dest interface{}) error { - ref := db.NewRef(refPath) - return ref.Get(context.Background(), dest) +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 (db *FireDB) Update(refPath string, data map[string]interface{}) error { - ref := db.NewRef(refPath) - return ref.Update(context.Background(), data) +func updateStudent(client *db.Client, userId string, updates map[string]interface{}) error { + ref := client.NewRef("students/" + userId) + return ref.Update(context.TODO(), updates) } -func (db *FireDB) Delete(refPath string) error { - ref := db.NewRef(refPath) - return ref.Delete(context.Background()) +func deleteStudent(client *db.Client, userId string) error { + ref := client.NewRef("students/" + userId) + return ref.Delete(context.TODO()) } -//todo: set up firebase, finish connecting to database +// Instructor CRUD +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()) +} + +// Parent CRUD +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()) +} diff --git a/database.rules.json b/database.rules.json deleted file mode 100644 index 1102a91..0000000 --- a/database.rules.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rules": { - ".read": false, - ".write": false - } -} \ No newline at end of file diff --git a/database_model.go b/database_model.go new file mode 100644 index 0000000..a8171d8 --- /dev/null +++ b/database_model.go @@ -0,0 +1,86 @@ +package main + +import ( + "time" + + "github.com/google/uuid" +) + +// Student struct for storing student information +type Student struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Age int `json:"age"` + LessonCredits float32 `json:"lesson_credits"` + Email string `json:"email"` + ContactNumber string `json:"contact_number"` + Class string `json:"class"` + Instructor string `json:"instructor"` + ParentName string `json:"parent_name"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// Instructor struct for storing instructor information +type Instructor struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + ContactNumber string `json:"contact_number"` + Email string `json:"email"` + BasePay float64 `json:"base_pay"` + NumberOfStudents int `json:"number_of_students"` + 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"` + Name string `json:"name"` + Email string `json:"email"` + ContactNo string `json:"contact_no"` + 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 { + return Student{ + ID: uuid.New(), + Name: name, + Age: age, + LessonCredits: lessonCredits, + Email: email, + ContactNumber: contactNumber, + Class: class, + Instructor: instructor, + ParentName: parentName, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } +} + +// NewInstructor creates a new Instructor instance +func NewInstructor(name string, contactNumber string, email string, basePay float64, numberOfStudents int) Instructor { + return Instructor{ + ID: uuid.New(), + Name: name, + ContactNumber: contactNumber, + Email: email, + BasePay: basePay, + NumberOfStudents: numberOfStudents, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } +} + +func NewParent(name string, email string, contactNo string) Parent { + return Parent{ + ID: uuid.New(), + Name: name, + Email: email, + ContactNo: contactNo, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } +} diff --git a/database_test.go b/database_test.go new file mode 100644 index 0000000..ddd2578 --- /dev/null +++ b/database_test.go @@ -0,0 +1,209 @@ +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) { +// 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() + // 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!") +} diff --git a/db_test.go b/db_test.go deleted file mode 100644 index bc6d17b..0000000 --- a/db_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "testing" -) - -func TestConnect(t *testing.T) { - // Create a new instance of FireDB. - db := FireDB{} - - // Call the Connect function. - err := db.Connect() - - // Check if there was an error during connection. - if err != nil { - t.Errorf("Failed to connect to Firebase: %v", err) - } - - // Check if the Firebase Realtime Database client is initialized. - if db.Client == nil { - t.Error("Firebase Realtime Database client is not initialized") - } -} diff --git a/decrypt_secret.sh b/decrypt_secret.sh new file mode 100644 index 0000000..a1cf4e9 --- /dev/null +++ b/decrypt_secret.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# Decrypt the file +# mkdir $HOME/secrets +# --batch to prevent interactive command +# --yes to assume "yes" for questions +gpg --quiet --batch --yes --decrypt --passphrase="$FIREBASE_ADMIN_PASSPHRASE" \ +--output edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json.gpg +# --output $HOME/secrets/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json.gpg + +# Optionally, you can output the decrypted file path for verification +echo "Decrypted file: edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json" \ No newline at end of file diff --git a/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json.gpg b/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json.gpg new file mode 100644 index 0000000..b57afbf Binary files /dev/null and b/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json.gpg differ diff --git a/go.mod b/go.mod index 768b17c..ee4a816 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22.3 require github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf require ( - cloud.google.com/go v0.113.0 // indirect + cloud.google.com/go v0.114.0 // indirect cloud.google.com/go/auth v0.4.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect @@ -14,9 +14,12 @@ require ( cloud.google.com/go/longrunning v0.5.7 // indirect cloud.google.com/go/storage v1.41.0 // indirect firebase.google.com/go v3.13.0+incompatible // indirect + firebase.google.com/go/v4 v4.14.1 // indirect + github.com/MicahParks/keyfunc v1.9.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/s2a-go v0.1.7 // indirect @@ -39,8 +42,9 @@ require ( golang.org/x/time v0.5.0 // indirect google.golang.org/api v0.181.0 // indirect google.golang.org/appengine v1.6.8 // indirect + google.golang.org/appengine/v2 v2.0.2 // indirect google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.34.1 // indirect diff --git a/go.sum b/go.sum index b76f01c..8d25f8c 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.113.0 h1:g3C70mn3lWfckKBiCVsAshabrDg01pQ0pnX1MNtnMkA= cloud.google.com/go v0.113.0/go.mod h1:glEqlogERKYeePz6ZdkcLJ28Q2I6aERgDDErBg9GzO8= +cloud.google.com/go v0.114.0 h1:OIPFAdfrFDFO2ve2U7r/H5SwSbBzEdrBdE7xkgwc+kY= +cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= cloud.google.com/go/auth v0.4.1 h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg= cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= @@ -17,7 +19,11 @@ cloud.google.com/go/storage v1.41.0 h1:RusiwatSu6lHeEXe3kglxakAmAbfV+rhtPqA6i8RB cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80= firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4= firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs= +firebase.google.com/go/v4 v4.14.1 h1:4qiUETaFRWoFGE1XP5VbcEdtPX93Qs+8B/7KvP2825g= +firebase.google.com/go/v4 v4.14.1/go.mod h1:fgk2XshgNDEKaioKco+AouiegSI9oTWVqRaBdTTGBoM= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/MicahParks/keyfunc v1.9.0 h1:lhKd5xrFHLNOWrDc4Tyb/Q1AJ4LCzQ48GVJyVIID3+o= +github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x95xuVNtM5jw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -36,12 +42,16 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -111,6 +121,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= @@ -158,6 +169,8 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/appengine/v2 v2.0.2 h1:MSqyWy2shDLwG7chbwBJ5uMyw6SNqJzhJHNDwYB0Akk= +google.golang.org/appengine/v2 v2.0.2/go.mod h1:PkgRUWz4o1XOvbqtWTkBtCitEJ5Tp4HoVEdMMYQR/8E= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= @@ -165,6 +178,8 @@ google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda h1:wu/KJm9KJwpfHWh google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae h1:AH34z6WAGVNkllnKs5raNq3yRq93VnjBG6rpfub/jYk= google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No= +google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= diff --git a/json_validator.go b/json_validator.go new file mode 100644 index 0000000..7e00390 --- /dev/null +++ b/json_validator.go @@ -0,0 +1,58 @@ +package main + +import ( + "encoding/json" + // "fmt" + "io" + + // "log" + "os" +) + +// func validateJSON(jsonFilePath string) { +// // Open the JSON file +// jsonFile, err := os.Open(jsonFilePath) +// if err != nil { +// log.Fatalf("Error opening JSON file: %v", err) +// } +// defer jsonFile.Close() + +// // Read the JSON file +// jsonBytes, err := io.ReadAll(jsonFile) +// if err != nil { +// log.Fatalf("Error reading JSON file: %v", err) +// } + +// // Validate JSON format +// var jsonData map[string]interface{} +// if err := json.Unmarshal(jsonBytes, &jsonData); err != nil { +// log.Fatalf("Error unmarshalling JSON: %v", err) +// } + +// fmt.Println("JSON is valid and correctly formatted.") +// } + +func validateJSON(jsonFilePath string) error { + // Open the JSON file + jsonFile, err := os.Open(jsonFilePath) + if err != nil { + return err + } + defer jsonFile.Close() + + // Read the JSON file + jsonData, err := io.ReadAll(jsonFile) + if err != nil { + return err + } + + // Validate JSON format + var parsedData interface{} + if err := json.Unmarshal(jsonData, &parsedData); err != nil { + return err + } + + // Additional validation logic can be added here + + return nil +} diff --git a/main.go b/main.go index d85d3e8..e0b82c9 100644 --- a/main.go +++ b/main.go @@ -5,40 +5,18 @@ import ( "net/http" ) -// func init() { -// // Example: Create a new student -// student := NewStudent("John Doe", 11, "Digital Navigators", "Scott Smith") -// err := fireDB.Create("/students/"+student.ID.String(), student) -// if err != nil { -// log.Fatalf("Failed to create student: %v", err) -// } -// fmt.Println("Student created successfully") +func init() { + // validateJSON("edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json") + // jsonFilePath := "$HOME/secrets/edusync-7bd5e-firebase-adminsdk-x49uh-af084a6314.json" -// // Example: Read the student data -// var readStudent Student -// err = fireDB.Read("/students/"+student.ID.String(), &readStudent) -// if err != nil { -// log.Fatalf("Failed to read student: %v", err) -// } -// fmt.Printf("Student data: %+v\n", readStudent) + // err := validateJSON(jsonFilePath) + // if err != nil { + // log.Fatalf("JSON validation failed: %v", err) + // } -// // Example: Update the student data -// updates := map[string]interface{}{ -// "Age": 12, -// } -// err = fireDB.Update("/students/"+student.ID.String(), updates) -// if err != nil { -// log.Fatalf("Failed to update student: %v", err) -// } -// fmt.Println("Student updated successfully") - -// // Example: Delete the student data -// err = fireDB.Delete("/students/" + student.ID.String()) -// if err != nil { -// log.Fatalf("Failed to delete student: %v", err) -// } -// fmt.Println("Student deleted successfully") -// } + // log.Println("JSON is valid.") + database() +} func main() { // http.HandleFunc("/1", serverhome) diff --git a/student_model.go b/student_model.go deleted file mode 100644 index 760d776..0000000 --- a/student_model.go +++ /dev/null @@ -1,57 +0,0 @@ -package main - -import ( - "time" - - "github.com/google/uuid" -) - -// Student struct for storing student information -type Student struct { - ID uuid.UUID `json:"id"` - Name string `json:"name"` - Age int `json:"age"` - Class string `json:"class"` - Instructor string `json:"instructor"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// Instructor struct for storing instructor information -type Instructor struct { - ID uuid.UUID `json:"id"` - Name string `json:"name"` - ContactNumber string `json:"contact_number"` - Email string `json:"email"` - BasePay float64 `json:"base_pay"` - NumberOfStudents int `json:"number_of_students"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// NewStudent creates a new Student instance -func NewStudent(name string, age int, class string, instructor string) Student { - return Student{ - ID: uuid.New(), - Name: name, - Age: age, - Class: class, - Instructor: instructor, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - } -} - -// NewInstructor creates a new Instructor instance -func NewInstructor(name string, contactNumber string, email string, basePay float64, numberOfStudents int) Instructor { - return Instructor{ - ID: uuid.New(), - Name: name, - ContactNumber: contactNumber, - Email: email, - BasePay: basePay, - NumberOfStudents: numberOfStudents, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - } -}