Skip to content

Commit

Permalink
Merge pull request #192 from markalbrand56/backend
Browse files Browse the repository at this point in the history
Backend
  • Loading branch information
Diego2250 authored Oct 9, 2023
2 parents 9ca254c + 4eb82e9 commit d5691a3
Show file tree
Hide file tree
Showing 8 changed files with 380 additions and 50 deletions.
67 changes: 47 additions & 20 deletions backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,8 @@ Elimina una oferta de trabajo. También elimina cualquier postulación asociada

### [POST] api/offers/applicants
Retorna los estudiantes que se han postulado a una oferta
> **Note**
> Auth required
## Params
``` json
Expand All @@ -558,25 +560,37 @@ Retorna los estudiantes que se han postulado a una oferta
#### Response
``` json
{
"Status": "200",
"Message": "Applicants returned successfully",
"Data": [
{
"apellido": "Albrand",
"carrera": 1,
"correo": "alb21004@uvg.edu.gt",
"cv": "cv",
"dpi": "2806089930101",
"estado": "Enviada",
"foto": "foto",
"id_estudiante": "alb21004@uvg.edu.gt",
"nacimiento": "2002-05-06T00:00:00Z",
"nombre": "Mark",
"semestre": 5,
"telefono": "58748587",
"universidad": "Universidad del Valle de Guatemala"
}
]
"status": 200,
"message": "Applicants returned successfully",
"data": [
{
"apellido": "Albrand",
"estado": "Enviada",
"foto": "alb21004_1504802402.jpg",
"id_estudiante": "alb21004@uvg.edu.gt",
"nacimiento": "2002-05-06T00:00:00Z",
"nombre": "Mark",
"universidad": "Universidad del Valle de Guatemala"
},
{
"apellido": "Contreras Arroyave",
"estado": "enviada",
"foto": "",
"id_estudiante": "contrerasmarce@gmail.com",
"nacimiento": "2002-10-24T00:00:00Z",
"nombre": "Marcela",
"universidad": "Universidad Francisco Marroquín"
},
{
"apellido": "Morales",
"estado": "En revisión",
"foto": "",
"id_estudiante": "mor21146@uvg.edu.gt",
"nacimiento": "2002-10-24T00:00:00Z",
"nombre": "Diego",
"universidad": "UVG"
}
]
}
```

Expand Down Expand Up @@ -670,6 +684,19 @@ Devuelve las postulaciones de un Estudiante.

```

### [DELETE] api/postulations/?id_postulacion=1
Elimina una postulación. El usuario se obtiene del token. Se pasa el id de la postulación como query param
> **Note**
> Auth required
#### Response
``` json
{
"status": 200,
"message": "Postulation deleted successfully",
"data": null
}
```

---
## Administradores
Expand Down Expand Up @@ -764,4 +791,4 @@ Suspende un usuario
"message": "User suspended successfully",
"data": null
}
```
```
14 changes: 14 additions & 0 deletions backend/configs/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
"os"
)

var DB *gorm.DB
var FileServer = "http://ec2-13-57-42-212.us-west-1.compute.amazonaws.com/files/"

func SetupDB() {
envs := EnvPG()
Expand All @@ -19,3 +21,15 @@ func SetupDB() {
fmt.Println("Connected to DB")
DB = db
}

func CreateDirIfNotExist(path string) (bool, error) {
if _, err := os.Stat(path); os.IsNotExist(err) {
fmt.Println("Directory " + path + " does not exist. Creating...")
err := os.Mkdir(path, 0777)
if err != nil {
return false, err
}
return true, nil
}
return false, nil
}
122 changes: 117 additions & 5 deletions backend/controllers/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ import (
"backend/utils"
"fmt"
"github.com/gin-gonic/gin"
"io"
"math/rand"
"net/http"
"os"
"path/filepath"
"strings"
)

func UpdateProfilePicture() gin.HandlerFunc {
return func(c *gin.Context) {
user, err := utils.ExtractTokenUsername(c)
acceptedFileTypes := []string{"png", "jpg", "jpeg"}

if err != nil {
c.JSON(http.StatusUnauthorized, responses.StandardResponse{
Expand All @@ -34,11 +39,33 @@ func UpdateProfilePicture() gin.HandlerFunc {
// get the file type from filename
fileType := file.Filename[strings.LastIndex(file.Filename, ".")+1:]

newFileName := user_stripped + "." + fileType
if !utils.Contains(acceptedFileTypes, fileType) {
c.JSON(http.StatusBadRequest, responses.StandardResponse{
Status: http.StatusBadRequest,
Message: "Invalid file type. Accepted file types are " + strings.Join(acceptedFileTypes, ", "),
Data: nil,
})
return
}

randomNumber := rand.Intn(9999999999-1111111111) + 1111111111
newFileName := user_stripped + "_" + fmt.Sprint(randomNumber) + "." + fileType

file.Filename = newFileName

dst := "./uploads/" + newFileName
fmt.Println("File: " + dst)

// Eliminar archivos antiguos con el mismo prefijo de usuario
if err := deleteFilesWithPrefix("./uploads/", user_stripped); err != nil {
c.JSON(http.StatusInternalServerError, responses.StandardResponse{
Status: http.StatusInternalServerError,
Message: "Failed to delete old files: " + err.Error(),
Data: nil,
})
return
}

// Actualizar en base de datos
userType, err := utils.ExtractTokenUserType(c)

Expand All @@ -53,13 +80,31 @@ func UpdateProfilePicture() gin.HandlerFunc {

if userType == "student" {
err = configs.DB.Model(&models.Estudiante{}).Where("correo = ?", user).Updates(models.Estudiante{Foto: newFileName}).Error
} else if userType == "company" {
} else if userType == "enterprise" {
err = configs.DB.Model(&models.Empresa{}).Where("correo = ?", user).Updates(models.Empresa{Foto: newFileName}).Error
}

// Upload the file to specific dst.
// Save locally
err = c.SaveUploadedFile(file, dst)
if err != nil {
c.JSON(http.StatusInternalServerError, responses.StandardResponse{
Status: http.StatusInternalServerError,
Message: "Failed to save file: " + err.Error(),
Data: nil,
})
return
}

// send the file via HTTP to the file server
url := "http://ec2-13-57-42-212.us-west-1.compute.amazonaws.com/upload/"
bearerToken := "Bearer " + utils.ExtractToken(c)

if err := utils.UploadFileToServer(url, bearerToken, file, dst); err != nil {
c.JSON(http.StatusInternalServerError, responses.StandardResponse{
Status: http.StatusInternalServerError,
Message: "Failed to upload file to server: " + err.Error(),
Data: nil,
})
return
}

Expand All @@ -73,10 +118,77 @@ func UpdateProfilePicture() gin.HandlerFunc {
}
}

func deleteFilesWithPrefix(directory, prefix string) error {
files, err := os.ReadDir(directory)
if err != nil {
return err
}

for _, file := range files {
fmt.Println(file.Name())
if strings.HasPrefix(file.Name(), prefix) {
filePath := filepath.Join(directory, file.Name())
fmt.Println("Deleting file: " + filePath)
if err := os.Remove(filePath); err != nil {
return err
}
}
}

return nil
}

func GetFile() gin.HandlerFunc {
return func(c *gin.Context) {
filename := c.Param("filename")
filePath := "./uploads/" + filename
c.File(filePath) // Esto sirve el archivo al cliente
fileURL := configs.FileServer + filename

// Realizar una solicitud GET al servidor de archivos externo
resp, err := http.Get(fileURL)
if err != nil {
c.JSON(http.StatusNotFound, responses.StandardResponse{
Status: http.StatusNotFound,
Message: "Error al obtener el archivo: " + err.Error(),
Data: nil,
})
return
}

defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
c.JSON(http.StatusInternalServerError, responses.StandardResponse{
Status: http.StatusInternalServerError,
Message: "Error al cerrar el cuerpo de la respuesta del servidor de archivos externo: " + err.Error(),
Data: nil,
})
return
}
}(resp.Body)

if resp.StatusCode != http.StatusOK {
c.JSON(http.StatusNotFound, responses.StandardResponse{
Status: http.StatusNotFound,
Message: "Archivo no encontrado en el servidor de archivos externo",
Data: nil,
})
return
}

// Configurar las cabeceras de la respuesta para el cliente
c.Header("Content-Type", resp.Header.Get("Content-Type"))
c.Header("Content-Disposition", "inline; filename="+filename)
c.Header("Content-Length", resp.Header.Get("Content-Length"))

// Copiar el cuerpo de la respuesta del servidor de archivos al cuerpo de la respuesta de Gin
_, err = io.Copy(c.Writer, resp.Body)
if err != nil {
c.JSON(http.StatusInternalServerError, responses.StandardResponse{
Status: http.StatusInternalServerError,
Message: "Error al copiar el cuerpo de la respuesta del servidor de archivos externo: " + err.Error(),
Data: nil,
})
return
}
}
}
Loading

0 comments on commit d5691a3

Please sign in to comment.