Skip to content

Commit

Permalink
Merge pull request #26 from WillyTonkas/feature/back/setup-application
Browse files Browse the repository at this point in the history
Feature/back/setup application
  • Loading branch information
FranCalveyra authored Dec 30, 2024
2 parents bcb6e84 + d05b77c commit 188a899
Show file tree
Hide file tree
Showing 18 changed files with 356 additions and 99 deletions.
4 changes: 0 additions & 4 deletions .github/ISSUE_TEMPLATE/non-functional-requirement.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ assignees: ''

---

Certainly! Here’s a **Non-Functional Requirement (NFR) Template** to document your non-functional requirements effectively:

---

### **Non-Functional Requirement (NFR) Template**

#### **1. Title**
Expand Down
20 changes: 12 additions & 8 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ name: CD Workflow
# TODO: Make the binary for the workflow to compile correctly
on:
push:
branches:
- main
branches: ["main", "dev"]
release:
types: [created]

Expand All @@ -20,26 +19,31 @@ jobs:
- name: Checkout code
uses: actions/checkout@v3


- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '1.23'

- name: Set binary name
id: set-binary-name
run: |
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
echo "BINARY_NAME=rpl-service" >> $GITHUB_ENV
else
echo "BINARY_NAME=rpl-service-dev" >> $GITHUB_ENV
- name: Build binary
run: go build -o rpl-service ../../main/main.go
run: go build -o ${{ env.BINARY_NAME }} ../../main/main.go

- name: Upload Go artifact
uses: actions/upload-artifact@v4
with:
name: rpl-service
path: rpl-service

name: ${{ env.BINARY_NAME }}
path: ${{ env.BINARY_NAME }}

- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v4
with:
github-token: ${{ secrets.DEPLOY_TOKEN }}
pages-branch: main
pages-path: /
pages-path: /
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.idea
*.iml
*.iml
.env
.gitmessage
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
3 changes: 3 additions & 0 deletions constants/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package constants

const EmptyString = ""
80 changes: 80 additions & 0 deletions controllers/courseController.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package controllers

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

const BaseURL = "/courses"

func CourseExists(w http.ResponseWriter, r *http.Request, db *gorm.DB) {
courseID := r.PathValue("id") // Get the course ID from the URL
if courseID == constants.EmptyString {
http.Error(w, "Course ID is required", http.StatusBadRequest)
return
}
courseUUID, err := uuid.Parse(courseID)
if err != nil {
http.Error(w, "Invalid course ID format", http.StatusBadRequest)
return
}

// Should return whether a user with that ID exists
if !users.CourseExists(db, courseUUID) { // TODO: change package name
http.Error(w, "Course not found", http.StatusNotFound)
return
}
w.WriteHeader(http.StatusOK)
_, err = w.Write([]byte("Course exists"))
if err != nil {
return
}
}

func CreateCourse(w http.ResponseWriter, r *http.Request, db *gorm.DB) {
// Should create a new course
var body models.Course
err := json.NewDecoder(r.Body).Decode(&body)
if err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
userID := uuid.New() // TODO: get the actual userID

currentCourse, creatingCourseErr := users.CreateCourse(db, userID, body.Name, body.Description)
if creatingCourseErr != nil {
http.Error(w, "Failed to create course", http.StatusInternalServerError)
return
}

response, err := json.Marshal(currentCourse)
if err != nil {
http.Error(w, "Failed to marshal response", http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
_, err = w.Write(response)
if err != nil {
http.Error(w, "Failed to write response", http.StatusInternalServerError)
return
}
}

var CourseExistsEndpoint = models.Endpoint{
Method: models.GET,
Path: BaseURL + "/course/exists/{id}",
HandlerFunction: CourseExists,
}

var CreateCourseEndpoint = models.Endpoint{
Method: models.POST,
Path: BaseURL + "/course",
HandlerFunction: CreateCourse,
}
File renamed without changes.
1 change: 0 additions & 1 deletion controllers/sampleController.go

This file was deleted.

18 changes: 17 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,23 @@ module rpl-service

go 1.23

require gorm.io/gorm v1.25.12
require (
github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.1
github.com/joho/godotenv v1.5.1
github.com/lib/pq v1.10.9
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-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.7.2 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/sync v0.10.0 // indirect
)

require (
//github.com/jackc/pgpassfile v1.0.0 // indirect
Expand Down
36 changes: 36 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,44 @@
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/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
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-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/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/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
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.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
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.

110 changes: 107 additions & 3 deletions main/main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,112 @@
package main

import "fmt"
import (
"database/sql"
"fmt"
"github.com/joho/godotenv"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"log"
"net/http"
"os"
"rpl-service/constants"
"rpl-service/controllers"
"rpl-service/models"
)

// 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()
if db == nil {
fmt.Println("Error starting the database")
return
}

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(controllers.CourseExistsEndpoint.Path, func(writer http.ResponseWriter, request *http.Request) {
controllers.CourseExistsEndpoint.HandlerFunction(writer, request, db)
})

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

serverPort := os.Getenv("SERVER_PORT")

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

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

func startDatabase() *gorm.DB {
// Retrieve environment variables
err := godotenv.Load(".env")
if err != nil {
return nil
}

host := os.Getenv("HOST")
user := os.Getenv("POSTGRES_USER")
password := os.Getenv("POSTGRES_PASSWORD")
dbname := os.Getenv("POSTGRES_DB")
port := os.Getenv("DATABASE_PORT")

if host == constants.EmptyString ||
user == constants.EmptyString ||
password == constants.EmptyString ||
dbname == constants.EmptyString ||
port == constants.EmptyString {
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)
}

// Enable uuid-ossp extension
err = db.Exec("CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"").Error
if err != nil {
log.Fatalf("failed to enable uuid-ossp extension: %v", err)
}

migrateSchemas(db)

return db
}

func migrateSchemas(db *gorm.DB) {
err := db.AutoMigrate(&models.Course{}, &models.Exercise{}, &models.Test{}, &models.IsEnrolled{})
if err != nil {
log.Fatalf("failed to migrate database: %v", err)
}
}
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)
}
Loading

0 comments on commit 188a899

Please sign in to comment.