Skip to content

Commit

Permalink
Merge branch 'spo-iitk:main' into pvf
Browse files Browse the repository at this point in the history
  • Loading branch information
AkshatGupta15 authored Jul 8, 2024
2 parents 86fed2b + df614c0 commit cdb8649
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 5 deletions.
4 changes: 2 additions & 2 deletions cmd/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,15 @@ func adminCompanyServer() *http.Server {
return server
}

func adminStudentServer() *http.Server {
func adminStudentServer(mail_channel chan mail.Mail) *http.Server {
PORT := viper.GetString("PORT.ADMIN.STUDENT")
engine := gin.New()
engine.Use(middleware.CORS())
engine.Use(middleware.Authenticator())
engine.Use(middleware.EnsurePsuedoAdmin())
engine.Use(gin.CustomRecovery(recoveryHandler))

student.AdminRouter(engine)
student.AdminRouter(mail_channel, engine)

server := &http.Server{
Addr: ":" + PORT,
Expand Down
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func main() {
})

g.Go(func() error {
return adminStudentServer().ListenAndServe()
return adminStudentServer(mail_channel).ListenAndServe()
})

g.Go(func() error {
Expand Down
49 changes: 49 additions & 0 deletions student/admin.clarification.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package student

import (
"net/http"

"github.com/gin-gonic/gin"
"github.com/spo-iitk/ras-backend/mail"
"github.com/spo-iitk/ras-backend/middleware"
"github.com/spo-iitk/ras-backend/util"
)

type postClarificationRequest struct {
Clarification string `json:"clarification" binding:"required"`
}

func postClarificationHandler(mail_channel chan mail.Mail) gin.HandlerFunc {
return func(ctx *gin.Context) {
sid, err := util.ParseUint(ctx.Param("sid"))
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

var student Student
err = getStudentByID(ctx, &student, sid)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

var request postClarificationRequest
err = ctx.ShouldBindJSON(&request)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

mail_channel <- mail.GenerateMail(student.IITKEmail, "Asking Clarification", request.Clarification)
mail_channel <- mail.GenerateMail(
middleware.GetUserID(ctx),
"Clarification Requested from "+student.Name,
"Dear "+middleware.GetUserID(ctx)+
"Clarification was requested from "+student.Name+
"\nSent Mail:\n"+
request.Clarification)

ctx.JSON(http.StatusOK, gin.H{"status": "Clarification Mail sent"})
}
}
118 changes: 118 additions & 0 deletions student/admin.document.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package student

import (
"net/http"
"strconv"

"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"github.com/spo-iitk/ras-backend/mail"
"github.com/spo-iitk/ras-backend/middleware"
"github.com/spo-iitk/ras-backend/util"
)

func getDocumentHandler(ctx *gin.Context) {
sid, err := strconv.ParseUint(ctx.Param("sid"), 10, 32)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

var documents []StudentDocument
err = getDocumentsByStudentID(ctx, &documents, uint(sid))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

ctx.JSON(http.StatusOK, documents)
}

type putDocumentVerifyRequest struct {
Verified bool `json:"verified"`
}

func putDocumentVerifyHandler(mail_channel chan mail.Mail) gin.HandlerFunc {
return func(ctx *gin.Context) {
did, err := util.ParseUint(ctx.Param("docid"))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

var req putDocumentVerifyRequest

err = ctx.BindJSON(&req)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

user := middleware.GetUserID(ctx)

var document StudentDocument
err = getDocumentByID(ctx, &document, uint(did))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

ok, err := updateDocumentVerify(ctx, did, req.Verified, user)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

if !ok {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Could not verify document"})
return
}

var student Student
err = getStudentByID(ctx, &student, document.StudentID)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

logrus.Infof("%v verified document with id %d, changed state to %v", user, did, req.Verified)

// Constructing the email message
msg := "Dear " + student.Name + "\n\n"
msg += "Your document (" + document.Type + ") with id " + strconv.Itoa(int(did)) + " has been "
if req.Verified {
msg += "ACCEPTED."
} else {
msg += "REJECTED."
}
msg += "\n\nBest regards,\nYour Verification Team"

mail_channel <- mail.GenerateMail(student.PersonalEmail, "Action taken on document", msg)

ctx.JSON(http.StatusOK, gin.H{"status": true})
}
}


func getAllDocumentHandler(ctx *gin.Context) {
var documents []StudentDocument
err := getAllDocuments(ctx, &documents)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

ctx.JSON(http.StatusOK, documents)
}

func getAllDocumentHandlerByType(ctx *gin.Context) {
docType := ctx.Param("type")
var documents []StudentDocument
err := getDocumentsByType(ctx, &documents, docType)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

ctx.JSON(http.StatusOK, documents)
}
2 changes: 1 addition & 1 deletion student/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func openConnection() {

db = database

err = db.AutoMigrate(&Student{})
err = db.AutoMigrate(&Student{}, &StudentDocument{})
if err != nil {
logrus.Fatal("Failed to migrate student database: ", err)
panic(err)
Expand Down
38 changes: 38 additions & 0 deletions student/db.document.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package student

import (
"github.com/gin-gonic/gin"
"gorm.io/gorm/clause"
)


func saveDocument(ctx *gin.Context, document *StudentDocument) error {
tx := db.WithContext(ctx).Save(document)
return tx.Error
}

func getDocumentsByStudentID(ctx *gin.Context, documents *[]StudentDocument, studentID uint) error {
tx := db.WithContext(ctx).Where("student_id = ?", studentID).Find(documents)
return tx.Error
}

func getDocumentByID(ctx *gin.Context, document *StudentDocument, docID uint) error {
tx := db.WithContext(ctx).First(document, docID)
return tx.Error
}

func getAllDocuments(ctx *gin.Context, documents *[]StudentDocument) error {
tx := db.WithContext(ctx).Find(documents)
return tx.Error
}

func getDocumentsByType(ctx *gin.Context, documents *[]StudentDocument, docType string) error {
tx := db.WithContext(ctx).Where("type = ?", docType).Find(documents)
return tx.Error
}

func updateDocumentVerify(ctx *gin.Context, docid uint, verified bool, user string) (bool, error){
var document StudentDocument
tx := db.WithContext(ctx).Model(&document).Clauses(clause.Returning{}).Where("id = ?", docid).Update("verified", verified).Update("action_taken_by", user)
return tx.RowsAffected == 1, tx.Error
}
11 changes: 11 additions & 0 deletions student/model.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package student

import (
"database/sql"

"gorm.io/gorm"
)

Expand Down Expand Up @@ -40,3 +42,12 @@ type Student struct {
IsEditable bool `json:"is_editable" gorm:"default:true"`
IsVerified bool `json:"is_verified" gorm:"default:false"`
}

type StudentDocument struct {
gorm.Model
StudentID uint `json:"sid"`
Type string `json:"type"`
Path string `json:"path"`
Verified sql.NullBool `json:"verified" gorm:"default:NULL"`
ActionTakenBy string `json:"action_taken_by"`
}
11 changes: 10 additions & 1 deletion student/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package student

import (
"github.com/gin-gonic/gin"
"github.com/spo-iitk/ras-backend/mail"
"github.com/spo-iitk/ras-backend/ras"
)

Expand All @@ -10,10 +11,12 @@ func StudentRouter(r *gin.Engine) {
{
student.PUT("", updateStudentHandler)
student.GET("", getStudentHandler)
student.POST("/document", postStudentDocumentHandler)
student.GET("/documents", getStudentDocumentHandler)
}
}

func AdminRouter(r *gin.Engine) {
func AdminRouter(mail_channel chan mail.Mail, r *gin.Engine) {
admin := r.Group("/api/admin/student")
{
admin.DELETE("/:sid", deleteStudentHandler)
Expand All @@ -24,5 +27,11 @@ func AdminRouter(r *gin.Engine) {
admin.PUT("/:sid/editable",makeStudentEdiatableHandler)
admin.PUT("/:sid/verify", verifyStudentHandler)
admin.GET("/:sid/history", ras.PlaceHolderController)

admin.POST("/:sid/clarification", postClarificationHandler(mail_channel))
admin.GET("/:sid/documents", getDocumentHandler)
admin.PUT("/document/:docid/verify", putDocumentVerifyHandler(mail_channel))
admin.GET("/documents", getAllDocumentHandler)
admin.GET("/documents/type/:type", getAllDocumentHandlerByType)
}
}
54 changes: 54 additions & 0 deletions student/student.document.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package student

import (
"net/http"

"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"github.com/spo-iitk/ras-backend/middleware"
)

func postStudentDocumentHandler(ctx *gin.Context) {
var document StudentDocument
email := middleware.GetUserID(ctx)

if err := ctx.ShouldBindJSON(&document); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
var student Student
err := getStudentByEmail(ctx, &student, email)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

document.StudentID = student.ID
err = saveDocument(ctx, &document)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

logrus.Infof("Document for student %d uploaded", student.ID)
ctx.JSON(http.StatusOK, gin.H{"status": "Successfully uploaded document"})
}

func getStudentDocumentHandler(ctx *gin.Context) {
email := middleware.GetUserID(ctx)
var student Student
err := getStudentByEmail(ctx, &student, email)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

var documents []StudentDocument
err = getDocumentsByStudentID(ctx, &documents, student.ID)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

ctx.JSON(http.StatusOK, documents)
}

0 comments on commit cdb8649

Please sign in to comment.