From e3a3712dde7b2a77f08288b9f1d988e04e476d7e Mon Sep 17 00:00:00 2001 From: FernandaCerezo Date: Thu, 20 Jan 2022 16:52:22 -0800 Subject: [PATCH] Go exercise with database and registration and query functions --- go.mod | 24 +++ go.sum | 35 +++++ intro-code/server/api/api.go | 141 ++++++++++++++++++ intro-code/server/controllers/output.go | 65 ++++++++ .../server/controllers/scheduled_items.go | 64 ++++++++ intro-code/server/controllers/users.go | 60 ++++++++ intro-code/server/database/connection.go | 25 ++++ intro-code/server/main.go | 27 ++++ 8 files changed, 441 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 intro-code/server/api/api.go create mode 100644 intro-code/server/controllers/output.go create mode 100644 intro-code/server/controllers/scheduled_items.go create mode 100644 intro-code/server/controllers/users.go create mode 100644 intro-code/server/database/connection.go create mode 100644 intro-code/server/main.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..34a35f9 --- /dev/null +++ b/go.mod @@ -0,0 +1,24 @@ +module intro-code + +go 1.17 +require github.com/gorilla/mux v1.8.0 + +require ( + github.com/google/uuid v1.3.0 // indirect + github.com/ubgo/gormuuid v0.0.4 // indirect + github.com/ubgo/gouuid v0.0.2 // indirect + golang.org/x/text v0.3.6 // indirect +) + +require ( + github.com/fatih/color v1.9.0 // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/githubnemo/CompileDaemon v1.4.0 // indirect + github.com/lib/pq v1.10.4 + github.com/mattn/go-colorable v0.1.4 // indirect + github.com/mattn/go-isatty v0.0.11 // indirect + github.com/radovskyb/watcher v1.0.7 // indirect + github.com/satori/go.uuid v1.2.0 // indirect + golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d + golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..683c5ee --- /dev/null +++ b/go.sum @@ -0,0 +1,35 @@ +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/githubnemo/CompileDaemon v1.4.0 h1:z96Qu4tj+RzRfF+L7f1O6E8ion5JQlisWeXWc2wzwDQ= +github.com/githubnemo/CompileDaemon v1.4.0/go.mod h1:/G125r3YBIp6rcXtCZfiEHwFzcl7GSsNSwylxSNrkMA= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= +github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE= +github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/ubgo/gormuuid v0.0.4 h1:crwNZLrE4NKaL9G5aG5ruQj2Lq6OgixeS3EZkP0cPnc= +github.com/ubgo/gormuuid v0.0.4/go.mod h1:VhGeR367PDjvD+QSmcQRVRNp4DQBRr2rdQE/MsfdVNU= +github.com/ubgo/gouuid v0.0.2 h1:ZCydOWMIiMZvp9Dqjx9PFC4ig19LOGtxJoP3IYX4Yhk= +github.com/ubgo/gouuid v0.0.2/go.mod h1:wcCyC0snR0yovyXyLHIrskUrFUybY7+8cK72TRad1HI= +golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d h1:1n1fc535VhN8SYtD4cDUyNlfpAF2ROMM9+11equK3hs= +golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/intro-code/server/api/api.go b/intro-code/server/api/api.go new file mode 100644 index 0000000..9649eba --- /dev/null +++ b/intro-code/server/api/api.go @@ -0,0 +1,141 @@ +package api + +import ( + "encoding/json" + "intro-code/intro-code/server/controllers" + "log" + "net/http" + + uuid "github.com/satori/go.uuid" +) + +type Data_scheduled struct { + Success bool `json:"success"` + Data []controllers.Scheduled_items `json:"data"` + Errors []string `json:"errors"` +} + +type Data_users struct { + Success bool `json:"success"` + Data []controllers.Users `json:"data"` + Errors []string `json:"errors"` +} + +type Data_outputs struct { + Success bool `json:"success"` + Data []controllers.Output `json:"data"` + Errors []string `json:"errors"` +} + +type response struct { + ID uuid.UUID `json:"UUID"` + Message string `json:"message,omitempty"` +} + +func CreateReminder(w http.ResponseWriter, req *http.Request) { + + w.Header().Set("Context-Type", "application/x-www-form-urlencoded") + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "POST") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + + var reminder controllers.Scheduled_items + + err := json.NewDecoder(req.Body).Decode(&reminder) + + if err != nil { + log.Fatalf("Unable to decode the request body. %v", err) + } + + insertID := controllers.InsertReminder(reminder) + + res := response{ + ID: insertID, + Message: "User created successfully", + } + + json.NewEncoder(w).Encode(res) +} + +func GetReminders(w http.ResponseWriter, req *http.Request) { + var reminder []controllers.Scheduled_items = controllers.GetAll() + + var data = Data_scheduled{true, reminder, make([]string, 0)} + json, _ := json.Marshal(data) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(json) +} + +func CreateUser(w http.ResponseWriter, req *http.Request) { + + w.Header().Set("Context-Type", "application/x-www-form-urlencoded") + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "POST") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + + var user controllers.Users + + err := json.NewDecoder(req.Body).Decode(&user) + + if err != nil { + log.Fatalf("Unable to decode the request body. %v", err) + } + + insertID := controllers.CreateUser(user) + res := response{ + ID: insertID, + Message: "User created successfully", + } + + json.NewEncoder(w).Encode(res) +} + +func GetAllUsers(w http.ResponseWriter, req *http.Request) { + var users []controllers.Users = controllers.GetAllUsers() + + var data = Data_users{true, users, make([]string, 0)} + + json, _ := json.Marshal(data) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(json) +} + +func CreateOutput(w http.ResponseWriter, req *http.Request) { + + w.Header().Set("Context-Type", "application/x-www-form-urlencoded") + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "POST") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + + var output controllers.Output + + err := json.NewDecoder(req.Body).Decode(&output) + + if err != nil { + log.Fatalf("Unable to decode the request body. %v", err) + } + + insertID := controllers.CreateOutput(output) + res := response{ + ID: insertID, + Message: "User created successfully", + } + + json.NewEncoder(w).Encode(res) +} + +func GetAllOutput(w http.ResponseWriter, req *http.Request) { + var outputs []controllers.Output = controllers.GetAllOutput() + + var data = Data_outputs{true, outputs, make([]string, 0)} + + json, _ := json.Marshal(data) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(json) +} diff --git a/intro-code/server/controllers/output.go b/intro-code/server/controllers/output.go new file mode 100644 index 0000000..553e4c0 --- /dev/null +++ b/intro-code/server/controllers/output.go @@ -0,0 +1,65 @@ +package controllers + +import ( + "log" + + "intro-code/intro-code/server/database" + + "github.com/lib/pq" + uuid "github.com/satori/go.uuid" +) + +type Output struct { + Id uuid.UUID + Description string `json:"description"` + Emails []string `json:"emails"` +} + +func CreateOutput(output Output) uuid.UUID { + db := database.GetConnection() + defer db.Close() + sqlStatement := `INSERT INTO output.output (id, description, emails) VALUES ($1, $2, $3) RETURNING id` + output.Id = uuid.NewV4() + err := db.QueryRow(sqlStatement, output.Id, "New Reminder sent", pq.Array(output.Emails)).Scan(&output.Id) + if err != nil { + log.Fatalf("Unable to execute the query. %v", err) + } + + return output.Id +} + +func GetAllOutput() []Output { + db := database.GetConnection() + rows, err := db.Query("SELECT * FROM output.output ORDER BY id") + if err != nil { + log.Fatal(err) + } + + defer rows.Close() + + var outputs []Output + for rows.Next() { + output := Output{} + + var Uid uuid.UUID + var description string + var emails []string + err := rows.Scan(&Uid, &description, pq.Array(&emails)) + if err != nil { + log.Fatal(err) + } + + output.Id = Uid + output.Description = description + output.Emails = emails + + outputs = append(outputs, output) + } + + err = rows.Err() + if err != nil { + log.Fatal(err) + } + + return outputs +} diff --git a/intro-code/server/controllers/scheduled_items.go b/intro-code/server/controllers/scheduled_items.go new file mode 100644 index 0000000..0976342 --- /dev/null +++ b/intro-code/server/controllers/scheduled_items.go @@ -0,0 +1,64 @@ +package controllers + +import ( + "intro-code/intro-code/server/database" + "log" + + "github.com/lib/pq" + uuid "github.com/satori/go.uuid" +) + +type Scheduled_items struct { + Id uuid.UUID + Description string `json:"description"` + Users []uuid.UUID `sql:",type:uuid[]" pg:",array"` +} + +func InsertReminder(reminder Scheduled_items) uuid.UUID { + db := database.GetConnection() + defer db.Close() + sqlStatement := `INSERT INTO scheduled.scheduled_items (id, description, users) VALUES ($1, $2, $3) RETURNING id` + reminder.Id = uuid.NewV4() + err := db.QueryRow(sqlStatement, reminder.Id, reminder.Description, pq.Array(reminder.Users)).Scan(&reminder.Id) + if err != nil { + log.Fatalf("Unable to execute the query. %v", err) + } + + return reminder.Id +} + +func GetAll() []Scheduled_items { + db := database.GetConnection() + rows, err := db.Query("SELECT * FROM scheduled.scheduled_items ORDER BY id") + if err != nil { + log.Fatal(err) + } + + defer rows.Close() + + var reminders []Scheduled_items + for rows.Next() { + reminder := Scheduled_items{} + + var Uid uuid.UUID + var description string + var users []uuid.UUID + err := rows.Scan(&Uid, &description, pq.Array(&users)) + if err != nil { + log.Fatal(err) + } + + reminder.Id = Uid + reminder.Description = description + reminder.Users = users + + reminders = append(reminders, reminder) + } + + err = rows.Err() + if err != nil { + log.Fatal(err) + } + + return reminders +} diff --git a/intro-code/server/controllers/users.go b/intro-code/server/controllers/users.go new file mode 100644 index 0000000..bbf81cc --- /dev/null +++ b/intro-code/server/controllers/users.go @@ -0,0 +1,60 @@ +package controllers + +import ( + "intro-code/intro-code/server/database" + "log" + + uuid "github.com/satori/go.uuid" +) + +type Users struct { + Id uuid.UUID + Email string `json:"email"` +} + +func CreateUser(user Users) uuid.UUID { + db := database.GetConnection() + defer db.Close() + sqlStatement := `INSERT INTO public.users (user_id, email) VALUES ($1, $2) RETURNING user_id` + user.Id = uuid.NewV4() + err := db.QueryRow(sqlStatement, user.Id, user.Email).Scan(&user.Id) + if err != nil { + log.Fatalf("Unable to execute the query. %v", err) + } + + return user.Id +} + +func GetAllUsers() []Users { + db := database.GetConnection() + rows, err := db.Query("SELECT * FROM public.users ORDER BY user_id") + if err != nil { + log.Fatal(err) + } + + defer rows.Close() + + var users []Users + for rows.Next() { + user := Users{} + + var Uid uuid.UUID + var email string + err := rows.Scan(&Uid, &email) + if err != nil { + log.Fatal(err) + } + + user.Id = Uid + user.Email = email + + users = append(users, user) + } + + err = rows.Err() + if err != nil { + log.Fatal(err) + } + + return users +} diff --git a/intro-code/server/database/connection.go b/intro-code/server/database/connection.go new file mode 100644 index 0000000..b8012c5 --- /dev/null +++ b/intro-code/server/database/connection.go @@ -0,0 +1,25 @@ +package database + +import ( + "database/sql" + "fmt" + "log" + + _ "github.com/lib/pq" +) + +func GetConnection() *sql.DB { + connStr := "postgres://postgres:server123@localhost/go_db?sslmode=disable" + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Fatal(err) + } + err = db.Ping() + + if err != nil { + panic(err) + } + + fmt.Println("Successfully connected!") + return db +} diff --git a/intro-code/server/main.go b/intro-code/server/main.go new file mode 100644 index 0000000..c95afab --- /dev/null +++ b/intro-code/server/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "intro-code/intro-code/server/api" + "log" + "net/http" + + "github.com/gorilla/mux" +) + +func main() { + // db := database.GetConnection() + //enrrutador + router := mux.NewRouter().StrictSlash(true) //StrictSlash especifica la URL correcta + apiRouter := router.PathPrefix("/api/").Subrouter() + //Users + apiRouter.HandleFunc("/users", api.GetAllUsers).Methods("GET") + apiRouter.HandleFunc("/users", api.CreateUser).Methods("POST") + //Reminders + apiRouter.HandleFunc("/reminders", api.GetReminders).Methods("GET") + apiRouter.HandleFunc("/reminders", api.CreateReminder).Methods("POST") + //Outputs + apiRouter.HandleFunc("/outputs", api.GetAllOutput).Methods("GET") + apiRouter.HandleFunc("/outputs", api.CreateOutput).Methods("POST") + + log.Fatal(http.ListenAndServe(":8000", router)) +}