diff --git a/application/admin.pvf.go b/application/admin.pvf.go new file mode 100644 index 0000000..2b158f7 --- /dev/null +++ b/application/admin.pvf.go @@ -0,0 +1,111 @@ +package application + +import ( + "net/http" + + "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 getAllPvfForAdminHandler(ctx *gin.Context) { + rid, err := util.ParseUint(ctx.Param("rid")) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + var jps []PVF + err = fetchAllPvfForAdmin(ctx, rid, &jps) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, jps) + +} + +func getPvfForAdminHandler(ctx *gin.Context) { + rid, err := util.ParseUint(ctx.Param("rid")) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + pid, err := util.ParseUint(ctx.Param("pid")) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + var jps PVF + err = fetchPvfForAdmin(ctx, rid, pid, &jps) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, jps) +} + +func sendVerificationLinkForPvfHandler(mail_channel chan mail.Mail) gin.HandlerFunc { + return func(ctx *gin.Context) { + pid, err := util.ParseUint(ctx.Param("pid")) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + var pvf PVF + + rid, err := util.ParseUint(ctx.Param("rid")) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + err = fetchPvfForAdmin(ctx, rid, pid, &pvf) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + token, err := middleware.GeneratePVFToken("akshat23@iitk.ac.in", pid, rid) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + logrus.Infof("A Token %s with id %d", token, pid) // to be removed + + // hardcode email + mail_channel <- mail.GenerateMail("iitkakshat@gmail.com", + "Verification requested on RAS", + "Dear "+pvf.MentorName+"PVF ID :"+util.ParseString(pid)+"Token : "+token+",\n\nWe got your request for registration on Recruitment Automation System, IIT Kanpur. We will get back to you soon. For any queries, please get in touch with us at spo@iitk.ac.in.") + + // mail_channel <- mail.GenerateMail("spo@iitk.ac.in", + // "Registration requested on RAS", + // "Company "+pvf.Duration+" has requested to be registered on RAS. The details are as follows:\n\n"+ + // "Name: "+pvf.CompanyUniversityName+"\n"+ + // "Designation: "+pvf.MentorDesignation+"\n"+ + // "Email: "+pvf.MentorEmail+"\n"+ + // "Phone: "+pvf.FileName+"\n"+ + // "Comments: "+pvf.Duration+"\n") + // ctx.JSON(http.StatusOK, gin.H{"pid": pid}) // to be removed + ctx.JSON(http.StatusOK, gin.H{"status": "Successfully Requested"}) + } +} + +func deletePVFHandler(ctx *gin.Context) { + pid, err := util.ParseUint(ctx.Param("pid")) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + err = deletePVF(ctx, pid) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"status": "deleted PVF"}) +} diff --git a/application/db.pvf.go b/application/db.pvf.go index 392d334..d1ac7c8 100644 --- a/application/db.pvf.go +++ b/application/db.pvf.go @@ -34,12 +34,13 @@ func fetchAllPvfForStudent(ctx *gin.Context, sid uint, rid uint, jps *[]PVF) err "mentor_email", "is_verified", "file_name", + "remarks", ). Order("id ASC"). Find(jps) return tx.Error } -func fetchPvfForStudent(ctx *gin.Context, sid uint, rid uint, pid uint, jps *[]PVF) error { +func fetchPvfForStudent(ctx *gin.Context, sid uint, rid uint, pid uint, jps *PVF) error { tx := db.WithContext(ctx). Where("student_recruitment_cycle_id = ? AND recruitment_cycle_id = ? AND id = ?", sid, rid, pid). Select( @@ -53,10 +54,17 @@ func fetchPvfForStudent(ctx *gin.Context, sid uint, rid uint, pid uint, jps *[]P "mentor_email", "is_verified", "file_name", + "remarks", ). Find(jps) return tx.Error } +func fetchPvfForAdmin(ctx *gin.Context, rid uint, pid uint, jps *PVF) error { + tx := db.WithContext(ctx). + Where("recruitment_cycle_id = ? AND id = ?", rid, pid). + Find(jps) + return tx.Error +} func fetchPvfForVerification(ctx *gin.Context, id uint, rid uint, jps *PVF) error { tx := db.WithContext(ctx). @@ -85,3 +93,16 @@ func verifyPvf(ctx *gin.Context, pvf *PVF) (bool, error) { Updates(map[string]interface{}{"is_verified": pvf.IsVerified}) return tx.RowsAffected > 0, tx.Error } + +func fetchAllPvfForAdmin(ctx *gin.Context, rid uint, jps *[]PVF) error { + tx := db.WithContext(ctx). + Where("recruitment_cycle_id = ?", rid). + Order("id DESC"). + Find(jps) + return tx.Error +} + +func deletePVF(ctx *gin.Context, pid uint) error { + tx := db.WithContext(ctx).Where("id = ?", pid).Delete(&PVF{}) + return tx.Error +} diff --git a/application/model.go b/application/model.go index bdd0abb..c49e1fd 100644 --- a/application/model.go +++ b/application/model.go @@ -133,7 +133,7 @@ type PVF struct { CompanyUniversityName string `json:"company_university_name"` Role string `json:"role"` Duration string `json:"duration"` - Description string `json:"description"` + Remarks string `json:"remarks"` MentorName string `json:"mentor_name"` MentorDesignation string `json:"mentor_designation"` MentorEmail string `json:"mentor_email"` diff --git a/application/router.go b/application/router.go index 7d2d177..72aa312 100644 --- a/application/router.go +++ b/application/router.go @@ -18,6 +18,11 @@ func AdminRouter(mail_channel chan mail.Mail, r *gin.Engine) { admin.DELETE("event/:eid/student", deleteAllStudentsFromEventHandler) admin.DELETE("event/:eid/student/:sid", deleteStudentFromEventHandler) + admin.GET("/pvf", getAllPvfForAdminHandler) + admin.GET("/pvf/:pid", getPvfForAdminHandler) + admin.GET("pvf/:pid/verification/send", sendVerificationLinkForPvfHandler(mail_channel)) + admin.DELETE("pvf/:pid", deletePVFHandler) + admin.GET("/company/:cid/proforma", getProformaByCompanyHandler) admin.GET("/proforma", getAllProformasHandler) @@ -64,6 +69,7 @@ func StudentRouter(mail_channel chan mail.Mail, r *gin.Engine) { student.POST("/pvf", postPvfForStudentHandler) student.GET("/pvf", getAllPvfForStudentHandler) student.GET("/pvf/:pid", getPvfForStudentHandler) + student.DELETE("pvf/:pid", deletePVFHandler) student.GET("/opening", getProformasForEligibleStudentHandler) student.GET("/opening/:pid", getApplicationHandler) @@ -102,11 +108,11 @@ func CompanyRouter(r *gin.Engine) { } func PvfVerificationRouter(r *gin.Engine) { - pvf := r.Group("/api/verification/application/rc/:rid") + pvf := r.Group("/api/verification") pvf.Use() { - pvf.GET("/pvf/:pid", getPvfForVerificationHandler) - pvf.PUT("pvf/:pid/verify", verifyPvfHandler) + pvf.GET("/pvf", getPvfForVerificationHandler) + // pvf.PUT("pvf/:pid/verify", verifyPvfHandler) pvf.PUT("/pvf", putPVFHandler) } } diff --git a/application/student.pvf.go b/application/student.pvf.go index 837c748..65e9f8c 100644 --- a/application/student.pvf.go +++ b/application/student.pvf.go @@ -56,18 +56,23 @@ func getAllPvfForStudentHandler(ctx *gin.Context) { } func getPvfForStudentHandler(ctx *gin.Context) { + sid := getStudentRCID(ctx) + if sid == 0 { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "SRCID not found"}) + return + } rid, err := util.ParseUint(ctx.Param("rid")) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } - id, err := util.ParseUint(ctx.Param("pid")) + pid, err := util.ParseUint(ctx.Param("pid")) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } var jps PVF - err = fetchPvfForVerification(ctx, id, rid, &jps) + err = fetchPvfForStudent(ctx, sid, rid, pid, &jps) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return diff --git a/application/verify.pvf.go b/application/verify.pvf.go index 3574948..5939747 100644 --- a/application/verify.pvf.go +++ b/application/verify.pvf.go @@ -4,63 +4,33 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/spo-iitk/ras-backend/middleware" "github.com/spo-iitk/ras-backend/util" ) func getPvfForVerificationHandler(ctx *gin.Context) { - rid, err := util.ParseUint(ctx.Param("rid")) - if err != nil { - ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - id, err := util.ParseUint("1") // id to be upadated - if err != nil { - ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - var jps PVF - err = fetchPvfForVerification(ctx, id, rid, &jps) - if err != nil { - ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } + // ctx.JSON(http.StatusOK, gin.H{"pid": middleware.GetPVFID(ctx)}) + pid := middleware.GetPVFID(ctx) - ctx.JSON(http.StatusOK, jps) -} - -func verifyPvfHandler(ctx *gin.Context) { - // var verifyPvfRequest PVF - // if err := ctx.ShouldBindJSON(&verifyPvfRequest); err != nil { - // ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - // return - // } // pid, err := util.ParseUint(ctx.Param("pid")) - // if err != nil { // ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) // return // } - - // verifyPvfRequest.ID = pid - // updated, err := verifyPvf(ctx, &verifyPvfRequest) + // rid, err := util.ParseUint(ctx.Param("rid")) // if err != nil { // ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) // return // } + rid := middleware.GetRcID(ctx) + var jps PVF + err := fetchPvfForVerification(ctx, pid, rid, &jps) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } - // if !updated { - // ctx.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "PVF not found"}) - // return - // } - - // if verifyPvfRequest.IsVerified { - // logrus.Infof("A PVF with id %d is verified", verifyPvfRequest.ID) - // ctx.JSON(http.StatusOK, gin.H{"status": "Successfully verified"}) - // } else { - // logrus.Infof("A PVF with id %d is unverified", verifyPvfRequest.ID) - // ctx.JSON(http.StatusOK, gin.H{"status": "Successfully unverified"}) - // } - + ctx.JSON(http.StatusOK, jps) } func putPVFHandler(ctx *gin.Context) { @@ -71,6 +41,9 @@ func putPVFHandler(ctx *gin.Context) { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } + pid := middleware.GetPVFID(ctx) + + jp.ID = pid if jp.ID == 0 { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "id is required"}) diff --git a/cmd/verification.go b/cmd/verification.go index 3b5e689..58c6f5c 100644 --- a/cmd/verification.go +++ b/cmd/verification.go @@ -15,6 +15,7 @@ func verificationServer() *http.Server { fmt.Print(PORT) engine := gin.New() engine.Use(middleware.CORS()) + engine.Use(middleware.PVFAuthenticator()) engine.Use(gin.CustomRecovery(recoveryHandler)) engine.Use(gin.Logger()) diff --git a/middleware/authenticator.go b/middleware/authenticator.go index bf061f2..c82cd84 100644 --- a/middleware/authenticator.go +++ b/middleware/authenticator.go @@ -65,3 +65,52 @@ func GetRoleID(ctx *gin.Context) constants.Role { return constants.Role(ctx.GetInt("roleID")) } + +func PVFAuthenticator() gin.HandlerFunc { + return func(ctx *gin.Context) { + authorizationHeader := ctx.GetHeader("authorization") + if len(authorizationHeader) == 0 { + ctx.AbortWithStatusJSON(http.StatusUnauthorized, + gin.H{"error": "authorization header is not provided"}) + return + } + + fields := strings.Fields(authorizationHeader) + if len(fields) < 2 { + ctx.AbortWithStatusJSON(http.StatusUnauthorized, + gin.H{"error": "invalid authorization header format"}) + return + } + + authorizationType := strings.ToLower(fields[0]) + if authorizationType != ("bearer") { + ctx.AbortWithStatusJSON(http.StatusUnauthorized, + gin.H{"error": "bearer not found"}) + return + } + + email, pid, rid, err := validatePVFToken(fields[1]) + // ctx.JSON(http.StatusAccepted, gin.H{"email": email, "pid": pid, "rid": rid}) // to be removed + if err != nil { + ctx.AbortWithStatusJSON(http.StatusUnauthorized, + gin.H{"error": "invalid token"}) + return + } + ctx.Set("email", email) + ctx.Set("pid", pid) + ctx.Set("rid", rid) + + ctx.Next() + } +} + +func GetEmail(ctx *gin.Context) string { + return ctx.GetString("email") +} + +func GetPVFID(ctx *gin.Context) uint { + return ctx.GetUint("pid") +} +func GetRcID(ctx *gin.Context) uint { + return ctx.GetUint("rid") +} diff --git a/middleware/jwt.go b/middleware/jwt.go index 1aff5cb..9900799 100644 --- a/middleware/jwt.go +++ b/middleware/jwt.go @@ -20,8 +20,9 @@ type CustomClaims struct { jwt.StandardClaims } type CustomPVFClaims struct { - email string `json:"email"` - pid uint `json:"pid"` + Email string `json:"email"` + Pid uint `json:"pid"` + Rid uint `json:"rid"` jwt.StandardClaims } @@ -70,17 +71,13 @@ func validateToken(encodedToken string) (string, uint, error) { return claims.UserID, claims.RoleID, nil } -func GeneratePVFToken(email string, pid uint, long bool) (string, error) { - var jwtExpiration int - if long { - jwtExpiration = jwtExpirationLong - } else { - jwtExpiration = jwtExpirationShort - } +func GeneratePVFToken(email string, pid uint, rid uint) (string, error) { + var jwtExpiration = 10080 // 7days claims := CustomPVFClaims{ email, pid, + rid, jwt.StandardClaims{ ExpiresAt: time.Now().Add(time.Duration(jwtExpiration) * time.Minute).Unix(), IssuedAt: jwt.TimeFunc().Unix(), @@ -92,7 +89,7 @@ func GeneratePVFToken(email string, pid uint, long bool) (string, error) { return tokenString, err } -func validatePVFToken(encodedToken string) (string, uint, error) { +func validatePVFToken(encodedToken string) (string, uint, uint, error) { claims := &CustomPVFClaims{} _, err := jwt.ParseWithClaims(encodedToken, claims, func(token *jwt.Token) (interface{}, error) { @@ -103,8 +100,7 @@ func validatePVFToken(encodedToken string) (string, uint, error) { }) if err != nil { - return "", 20, err + return "", 20, 20, err } - - return claims.email, claims.pid, nil + return claims.Email, claims.Pid, claims.Rid, nil }