diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8565f25 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +A companion repo for the Udemy course ("Go - The Complete Guide")[https://www.udemy.com/share/109Zxy3@5weOyI1zPY1wYhrd-_RWBlbsz-IdPECfz9MAMP-VcJdAKgcTfeJsDhVTi6kQt6_PDQ==/] by Maximilian Schwarzmüller. \ No newline at end of file diff --git a/rest-api/api-test/create-event.http b/rest-api/api-test/create-event.http new file mode 100644 index 0000000..dc47027 --- /dev/null +++ b/rest-api/api-test/create-event.http @@ -0,0 +1,9 @@ +POST http://localhost:8080/events +content-type: application/json + +{ + "name": "Test event", + "description": "A test event", + "location": "A test location", + "dateTime": "2025-01-01T15:30:00.000Z" +} \ No newline at end of file diff --git a/rest-api/api-test/create-user.http b/rest-api/api-test/create-user.http new file mode 100644 index 0000000..12a5422 --- /dev/null +++ b/rest-api/api-test/create-user.http @@ -0,0 +1,7 @@ +POST http://localhost:8080/signup +content-type: application/json + +{ + "email": "test@example.com", + "password": "test" +} \ No newline at end of file diff --git a/rest-api/api-test/delete-event.http b/rest-api/api-test/delete-event.http new file mode 100644 index 0000000..dde25a9 --- /dev/null +++ b/rest-api/api-test/delete-event.http @@ -0,0 +1 @@ +DELETE http://localhost:8080/events/1 \ No newline at end of file diff --git a/rest-api/api-test/get-events.http b/rest-api/api-test/get-events.http new file mode 100644 index 0000000..c46b734 --- /dev/null +++ b/rest-api/api-test/get-events.http @@ -0,0 +1 @@ +GET http://localhost:8080/events \ No newline at end of file diff --git a/rest-api/api-test/get-single-event.http b/rest-api/api-test/get-single-event.http new file mode 100644 index 0000000..2357ae8 --- /dev/null +++ b/rest-api/api-test/get-single-event.http @@ -0,0 +1 @@ +GET http://localhost:8080/events/1 \ No newline at end of file diff --git a/rest-api/api-test/update-event.http b/rest-api/api-test/update-event.http new file mode 100644 index 0000000..aa90a5b --- /dev/null +++ b/rest-api/api-test/update-event.http @@ -0,0 +1,9 @@ +PUT http://localhost:8080/events/1 +content-type: application/json + +{ + "name": "Updated test event", + "description": "A test event", + "location": "Test location (updated)", + "dateTime": "2025-01-01T15:30:00.000Z" +} \ No newline at end of file diff --git a/rest-api/api.db b/rest-api/api.db new file mode 100644 index 0000000..51435f8 Binary files /dev/null and b/rest-api/api.db differ diff --git a/rest-api/db/db.go b/rest-api/db/db.go new file mode 100644 index 0000000..ba6fddd --- /dev/null +++ b/rest-api/db/db.go @@ -0,0 +1,57 @@ +package db + +import ( + "database/sql" + + _ "github.com/mattn/go-sqlite3" +) + +var DB *sql.DB + +func InitDB() { + var err error + DB, err = sql.Open("sqlite3", "api.db") + + if err != nil { + panic("Could not connect to database") + } + + DB.SetMaxOpenConns(10) + DB.SetMaxIdleConns(5) + + createTables() +} + +func createTables() { + createUsersTable := ` + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + email TEXT NOT NULL UNIQUE, + password TEXT NOT NULL + ) + ` + + _, err := DB.Exec(createUsersTable) + + if err != nil { + panic("Could not create users table.") + } + + createEventsTable := ` + CREATE TABLE IF NOT EXISTS events ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + description TEXT NOT NULL, + location TEXT NOT NULL, + dateTime DATETIME NOT NULL, + user_id INTEGER, + FOREIGN KEY(user_id) REFERENCES users(id) + ) + ` + + _, err = DB.Exec(createEventsTable) + + if err != nil { + panic("Could not create table") + } +} diff --git a/rest-api/go.mod b/rest-api/go.mod new file mode 100644 index 0000000..9ad9f74 --- /dev/null +++ b/rest-api/go.mod @@ -0,0 +1,37 @@ +module example.com/rest-api + +go 1.25.0 + +require ( + github.com/bytedance/gopkg v0.1.4 // indirect + github.com/bytedance/sonic v1.15.2 // indirect + github.com/bytedance/sonic/loader v0.5.1 // indirect + github.com/cloudwego/base64x v0.1.7 // indirect + github.com/gabriel-vasile/mimetype v1.4.13 // indirect + github.com/gin-contrib/sse v1.1.1 // indirect + github.com/gin-gonic/gin v1.12.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.30.3 // indirect + github.com/goccy/go-json v0.10.6 // indirect + github.com/goccy/go-yaml v1.19.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.4.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect + github.com/mattn/go-sqlite3 v1.14.47 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.4.2 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.60.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.1 // indirect + go.mongodb.org/mongo-driver/v2 v2.7.0 // indirect + golang.org/x/arch v0.28.0 // indirect + golang.org/x/crypto v0.53.0 // indirect + golang.org/x/net v0.56.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/text v0.38.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect +) diff --git a/rest-api/go.sum b/rest-api/go.sum new file mode 100644 index 0000000..af5a401 --- /dev/null +++ b/rest-api/go.sum @@ -0,0 +1,79 @@ +github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= +github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= +github.com/bytedance/sonic v1.15.2 h1:90H+rcF/FwLXwfB1cudOLq/je83n683Utf4Cbp0xHCo= +github.com/bytedance/sonic v1.15.2/go.mod h1:mT2NbXunuaEbnZ+mRIX/vYqKISmgEuHFDI4UzmKx2SA= +github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= +github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI= +github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= +github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko= +github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s= +github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= +github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.30.3 h1:4MU6YkEwx7GbcPJOZxrtbu+QfF3pJLJuaYTeAH0DYy8= +github.com/go-playground/validator/v10 v10.30.3/go.mod h1:4Axh7oCNGcoGkqLoE4YWt6n20mcEIsPRlB7vPk3lpyc= +github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= +github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw= +github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= +github.com/mattn/go-sqlite3 v1.14.47 h1:jOBI62gS7nKeZv+as1oGEy0+1qISgXwH/QBlR6KbfIo= +github.com/mattn/go-sqlite3 v1.14.47/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.4.2 h1:M2fKKbmyvI+hGId/D0W64qDBMVhJnNR10O5gIbMc//Q= +github.com/pelletier/go-toml/v2 v2.4.2/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.60.0 h1:xcQioE8OM66UQLeUMHltK1CCcOu3JbVB4JAQdDQSB+0= +github.com/quic-go/quic-go v0.60.0/go.mod h1:wpKpjmPpftl30sL6pFh7REVpjbcCVy4zt2vDyK1TuJk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= +github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +go.mongodb.org/mongo-driver/v2 v2.7.0 h1:RO+zqavD2/GCL3cxOMyZhx6R9Irzr8/6gsoqx5tcY/c= +go.mongodb.org/mongo-driver/v2 v2.7.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= +golang.org/x/arch v0.28.0 h1:wVwVdqsTuUbJvhYVCspQYwZXHNYeLSoZnmHD+ggddpQ= +golang.org/x/arch v0.28.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= +golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/rest-api/main.go b/rest-api/main.go new file mode 100644 index 0000000..7b3badc --- /dev/null +++ b/rest-api/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "example.com/rest-api/db" + "example.com/rest-api/routes" + "github.com/gin-gonic/gin" +) + +func main() { + db.InitDB() + server := gin.Default() + + routes.RegisterRoutes(server) + + server.Run(":8080") +} diff --git a/rest-api/main.txt b/rest-api/main.txt new file mode 100644 index 0000000..e69de29 diff --git a/rest-api/models/event.go b/rest-api/models/event.go new file mode 100644 index 0000000..3bc570e --- /dev/null +++ b/rest-api/models/event.go @@ -0,0 +1,107 @@ +package models + +import ( + "time" + + "example.com/rest-api/db" +) + +type Event struct { + ID int64 + Name string `binding:"required"` + Description string `binding:"required"` + Location string `binding:"required"` + DateTime time.Time `binding:"required"` + UserID int +} + +var events []Event = []Event{} + +func (e Event) Save() error { + query := ` + INSERT INTO events(name, description, location, dateTime, user_id) + VALUES (?, ?, ?, ?, ?)` + stmt, err := db.DB.Prepare(query) + + if err != nil { + return err + } + // defer stmt.Close() + result, err := stmt.Exec(e.Name, e.Description, e.Location, e.DateTime, e.UserID) + if err != nil { + return err + } + id, err := result.LastInsertId() + e.ID = id + return err +} + +func GetAllEvents() ([]Event, error) { + query := "SELECT * FROM events" + rows, err := db.DB.Query(query) + if err != nil { + return nil, err + } + defer rows.Close() + + var events []Event + + for rows.Next() { + var event Event + err := rows.Scan(&event.ID, &event.Name, &event.Description, &event.Location, &event.DateTime, &event.UserID) + + if err != nil { + return nil, err + } + + events = append(events, event) + } + + return events, nil +} + +func GetEventByID(id int64) (*Event, error) { + query := "SELECT * FROM events WHERE id = ?" + row := db.DB.QueryRow(query, id) + + var event Event + err := row.Scan(&event.ID, &event.Name, &event.Description, &event.Location, &event.DateTime, &event.UserID) + if err != nil { + return nil, err + } + + return &event, nil +} + +func (event Event) Update() error { + query := ` + UPDATE events + SET name = ?, description = ?, location = ?, dateTime = ? + WHERE id = ? + ` + stmt, err := db.DB.Prepare(query) + + if err != nil { + return err + } + + defer stmt.Close() + + _, err = stmt.Exec(event.Name, event.Description, event.Location, event.DateTime, event.UserID) + return err +} + +func (event Event) Delete() error { + query := "DELETE FROM events WHERE id = ?" + stmt, err := db.DB.Prepare(query) + + if err != nil { + return err + } + + defer stmt.Close() + + _, err = stmt.Exec(event.ID) + + return err +} diff --git a/rest-api/models/user.go b/rest-api/models/user.go new file mode 100644 index 0000000..80bd9bf --- /dev/null +++ b/rest-api/models/user.go @@ -0,0 +1,40 @@ +package models + +import ( + "example.com/rest-api/db" + "example.com/rest-api/utils" +) + +type User struct { + ID int64 + Email string `binding:"required"` + Password string `binding:"required"` +} + +func (u User) Save() error { + query := "INSERT INTO users(email, password) VALUES (?, ?)" + stmt, err := db.DB.Prepare(query) + + if err != nil { + return err + } + + defer stmt.Close() + + hashedPassword, err := utils.HashPassword(u.Password) + + if err != nil { + return err + } + + result, err := stmt.Exec(u.Email, hashedPassword) + + if err != nil { + return err + } + + userId, err := result.LastInsertId() + + u.ID = userId + return err +} diff --git a/rest-api/routes/events.go b/rest-api/routes/events.go new file mode 100644 index 0000000..b58e0e0 --- /dev/null +++ b/rest-api/routes/events.go @@ -0,0 +1,110 @@ +package routes + +import ( + "net/http" + "strconv" + + "example.com/rest-api/models" + "github.com/gin-gonic/gin" +) + +func getEvents(context *gin.Context) { + events, err := models.GetAllEvents() + if err != nil { + context.JSON(http.StatusInternalServerError, gin.H{"message": "Could not fetch events."}) + } + context.JSON(http.StatusOK, events) +} + +func getEvent(context *gin.Context) { + eventId, err := strconv.ParseInt(context.Param("id"), 10, 64) + if err != nil { + context.JSON(http.StatusBadRequest, gin.H{"message": "Could not parse event id."}) + return + } + + event, err := models.GetEventByID(eventId) + + if err != nil { + context.JSON(http.StatusInternalServerError, gin.H{"message": "Could not fetch event."}) + return + } + + context.JSON(http.StatusOK, event) +} + +func createEvent(context *gin.Context) { + var event models.Event + err := context.ShouldBindJSON(&event) + + if err != nil { + context.JSON(http.StatusBadRequest, gin.H{"message": "Could not parse request data"}) + return + } + + event.ID = 1 + event.UserID = 1 + + err = event.Save() + + if err != nil { + context.JSON(http.StatusInternalServerError, gin.H{"message": "Could not create event."}) + } + + context.JSON(http.StatusCreated, gin.H{"message": "Event created!", "event": event}) +} + +func updateEvent(context *gin.Context) { + eventId, err := strconv.ParseInt(context.Param("id"), 10, 64) + if err != nil { + context.JSON(http.StatusBadRequest, gin.H{"message": "Could not parse event id."}) + return + } + + _, err = models.GetEventByID(eventId) + + if err != nil { + context.JSON(http.StatusInternalServerError, gin.H{"message": "Could not fetch the event."}) + return + } + + var updatedEvent models.Event + err = context.ShouldBindJSON(&updatedEvent) + + if err != nil { + context.JSON(http.StatusBadRequest, gin.H{"message": "Could not parse request data"}) + return + } + + updatedEvent.ID = eventId + err = updatedEvent.Update() + if err != nil { + context.JSON(http.StatusInternalServerError, gin.H{"message": "Could not update the event."}) + return + } + context.JSON(http.StatusOK, gin.H{"message": "Event updated successfully."}) +} + +func deleteEvent(context *gin.Context) { + eventId, err := strconv.ParseInt(context.Param("id"), 10, 64) + if err != nil { + context.JSON(http.StatusBadRequest, gin.H{"message": "Could not parse event id."}) + return + } + + event, err := models.GetEventByID(eventId) + + if err != nil { + context.JSON(http.StatusInternalServerError, gin.H{"message": "Could not fetch the event."}) + return + } + + err = event.Delete() + + if err != nil { + context.JSON(http.StatusInternalServerError, gin.H{"message": "Could not delete the event."}) + return + } + + context.JSON(http.StatusOK, gin.H{"message": "Event deleted successfully."}) +} diff --git a/rest-api/routes/routes.go b/rest-api/routes/routes.go new file mode 100644 index 0000000..4607459 --- /dev/null +++ b/rest-api/routes/routes.go @@ -0,0 +1,12 @@ +package routes + +import "github.com/gin-gonic/gin" + +func RegisterRoutes(server *gin.Engine) { + server.GET("/events", getEvents) + server.GET("/events/:id", getEvent) + server.POST("/events", createEvent) + server.PUT("/events/:id", updateEvent) + server.DELETE("/events/:id", deleteEvent) + server.POST("/signup", signup) +} diff --git a/rest-api/routes/users.go b/rest-api/routes/users.go new file mode 100644 index 0000000..80f1b09 --- /dev/null +++ b/rest-api/routes/users.go @@ -0,0 +1,28 @@ +package routes + +import ( + "net/http" + + "example.com/rest-api/models" + "github.com/gin-gonic/gin" +) + +func signup(context *gin.Context) { + var user models.User + + err := context.ShouldBindJSON(&user) + + if err != nil { + context.JSON(http.StatusBadRequest, gin.H{"message": "Could not parse request data."}) + return + } + + err = user.Save() + + if err != nil { + context.JSON(http.StatusInternalServerError, gin.H{"message": "Could not save user."}) + return + } + + context.JSON(http.StatusCreated, gin.H{"message": "User created successfully"}) +} diff --git a/rest-api/utils/hash.go b/rest-api/utils/hash.go new file mode 100644 index 0000000..33a59b0 --- /dev/null +++ b/rest-api/utils/hash.go @@ -0,0 +1,8 @@ +package utils + +import "golang.org/x/crypto/bcrypt" + +func HashPassword(password string) (string, error) { + bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) + return string(bytes), err +}