Skip to content

Commit

Permalink
feat(general): Changed main application, added a controller, an endpo…
Browse files Browse the repository at this point in the history
…int, changed some settings for linting

Changed main application for it to be a web service, paired it to environment variables, added some business logic, created a struct type for Endpoints, renamed some files, changed some parameters types

Referred issue: #4
  • Loading branch information
FranCalveyra committed Dec 28, 2024
1 parent bcb6e84 commit 35de299
Show file tree
Hide file tree
Showing 15 changed files with 245 additions and 80 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea
*.iml
*.iml
.env
4 changes: 2 additions & 2 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ linters:
- fatcontext # detects nested contexts in loops
- funlen # tool for detection of long functions
- gocheckcompilerdirectives # validates go compiler directive comments (//go:)
- gochecknoglobals # checks that no global variables exist
# - gochecknoglobals # checks that no global variables exist #TODO: enable after fixing issues
- gochecknoinits # checks that no init functions are present in Go code
- gochecksumtype # checks exhaustiveness on Go "sum types"
- gocognit # computes and checks the cognitive complexity of functions
Expand All @@ -260,7 +260,7 @@ linters:
- gomoddirectives # manages the use of 'replace', 'retract', and 'excludes' directives in go.mod
- gomodguard # allow and block lists linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations
- goprintffuncname # checks that printf-like functions are named with f at the end
- gosec # inspects source code for security problems
# - gosec # inspects source code for security problems #TODO: enable after fixing issues
- iface # checks the incorrect use of interfaces, helping developers avoid interface pollution
- intrange # finds places where for loops could make use of an integer range
- lll # reports long lines
Expand Down
1 change: 0 additions & 1 deletion controllers/sampleController.go

This file was deleted.

37 changes: 37 additions & 0 deletions controllers/userController.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package controllers

import (
"github.com/google/uuid"
"gorm.io/gorm"
"net/http"
"rpl-service/models"
"rpl-service/services/users"
)

const BaseURL = "/users"

func CourseExists(w http.ResponseWriter, r *http.Request, db *gorm.DB) {
courseID := r.URL.Query().Get("id") // Get the course ID from the URL
if courseID == "" {
w.WriteHeader(http.StatusBadRequest)
return
}
courseUUID, err := uuid.Parse(courseID)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}

// Should return whether a user with that ID exists
if !users.CourseExists(db, courseUUID) {
w.WriteHeader(http.StatusNotFound)
return
}
w.WriteHeader(http.StatusOK)
}

var CourseExistsEndpoint = models.Endpoint{
Method: models.GET,
Path: BaseURL + "/course/{id}",
HandlerFunction: CourseExists,
}
File renamed without changes.
15 changes: 14 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,20 @@ module rpl-service

go 1.23

require gorm.io/gorm v1.25.12
require (
github.com/google/uuid v1.6.0
gorm.io/driver/postgres v1.5.11
gorm.io/gorm v1.25.12
)

require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/sync v0.10.0 // indirect
)

require (
//github.com/jackc/pgpassfile v1.0.0 // indirect
Expand Down
30 changes: 30 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
14 changes: 0 additions & 14 deletions main.go

This file was deleted.

79 changes: 76 additions & 3 deletions main/main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,81 @@
package main

import "fmt"
import (
"database/sql"
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"log"
"net/http"
"os"
"rpl-service/controllers"
)

// Should run the main web application
// This is a mock version of the main application, this is the binary to compile on CD.
func main() {
// Should run the main web application
fmt.Println("Hello World!")
// Start the database
startServer()
}

func startServer() {
db := startDatabase()

s, serverError := db.DB()
if serverError != nil {
return
}

// Defer its closing
defer func(db *sql.DB) {
err := db.Close()
if err != nil {
return
}
}(s)

// Here should go the functions for each endpoint
http.HandleFunc("/", func(_ http.ResponseWriter, _ *http.Request) {
fmt.Println("Hello, World!") // Mock endpoint
})

http.HandleFunc(controllers.CourseExistsEndpoint.Path, func(writer http.ResponseWriter, request *http.Request) {
controllers.CourseExistsEndpoint.HandlerFunction(writer, request, db)
})

serverPort := os.Getenv("SERVER_PORT")
fmt.Println(serverPort)

if serverPort == "" {
log.Panic("serverPort environment variable is not set")
}

serverError = http.ListenAndServe(":"+serverPort, nil)
if serverError != nil {
return
}
}

func startDatabase() *gorm.DB {
// Retrieve environment variables
host := os.Getenv("DATABASE_URL")
user := os.Getenv("POSTGRES_USER")
password := os.Getenv("POSTGRES_PASSWORD")
dbname := os.Getenv("POSTGRES_DB")
port := os.Getenv("DATABASE_PORT")

if host == "" || user == "" || password == "" || dbname == "" || port == "" {
log.Fatal("One or more database environment variables are not set")
}

// Database connection string
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable", host, user, password, dbname, port)

// Open the database connection
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatalf("failed to connect to the database: %v", err)
}

return db
}
19 changes: 19 additions & 0 deletions models/controllerModel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package models

import (
"gorm.io/gorm"
"net/http"
)

const (
GET = "GET"
POST = "POST"
PUT = "PUT"
DELETE = "DELETE"
)

type Endpoint struct {
Method string
Path string
HandlerFunction func(w http.ResponseWriter, r *http.Request, db *gorm.DB)
}
47 changes: 47 additions & 0 deletions models/courseModel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package models

import (
"github.com/google/uuid"
"gorm.io/gorm"
)

type Course struct {
gorm.Model
ID uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4()" json:"id"`
Name string `json:"name"`
Description string `json:"description"`
}

type Exercise struct {
gorm.Model
ID uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4()"`
Name string `json:"name"`
Description string `json:"description"`
BaseCode string `json:"base-code"`
Points int `json:"points"`
UnitNumber int `json:"unit_number"`
TestIDs []uuid.UUID `gorm:"foreignkey:ExerciseId" json:"testIDs"`
}

type Test struct {
gorm.Model
ID uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4()"`
Name string `json:"name"`
Input []string `json:"input"`
Output []string `json:"output"`
}

type TestDTO struct {
Name string `json:"name"`
Input []string `json:"input"`
Output []string `json:"output"`
}

type ExerciseDTO struct {
Name string `json:"name"`
Description string `json:"description"`
BaseCode string `json:"base-code"`
Points int `json:"points"`
UnitNumber int `json:"unit_number"`
TestData []TestDTO `json:"test-data"`
}
41 changes: 0 additions & 41 deletions models/courseModels.go

This file was deleted.

1 change: 0 additions & 1 deletion models/sampleModel.go

This file was deleted.

5 changes: 3 additions & 2 deletions models/userModel.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package models

import (
"github.com/google/uuid"
"gorm.io/gorm"
)

type IsEnrolled struct {
gorm.Model
UserID uint
CourseID uint
UserID uuid.UUID
CourseID uuid.UUID
IsOwner bool
}

Expand Down
Loading

0 comments on commit 35de299

Please sign in to comment.