Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Endpoints and oauth for organisers #194

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions controllers/mentor.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func RegisterMentor(w http.ResponseWriter, r *http.Request) {
}

// Check if the JWT login username is the same as the mentor's given username
login_username := r.Context().Value(middleware.LOGIN_CTX_USERNAME_KEY).(string)
login_username := r.Context().Value(middleware.LOGIN_CTX_USERNAME_KEY).(utils.LoginJwtFields).Username

err = utils.DetectSessionHijackAndRespond(r, w, reqFields.Username, login_username, "Login username and given username do not match.")
if err != nil {
Expand Down Expand Up @@ -225,7 +225,7 @@ func FetchMentorDashboard(w http.ResponseWriter, r *http.Request) {

var modelMentor models.Mentor

login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY))
login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY)).(utils.LoginJwtFields).Username
tx := db.
Table("mentors").
Where("username = ?", login_username).
Expand Down Expand Up @@ -278,7 +278,7 @@ func UpdateMentorDetails(w http.ResponseWriter, r *http.Request) {

var modelMentor models.Mentor

login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY))
login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY)).(utils.LoginJwtFields).Username
tx := db.
Table("mentors").
Where("username = ?", login_username).
Expand Down Expand Up @@ -337,7 +337,7 @@ func GetMentorDetails(w http.ResponseWriter, r *http.Request) {
app := r.Context().Value(middleware.APP_CTX_KEY).(*middleware.App)
db := app.Db

login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY))
login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY)).(utils.LoginJwtFields).Username

mentor := models.Mentor{}
tx := db.
Expand Down
33 changes: 33 additions & 0 deletions controllers/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package controllers

import (
"fmt"
"net/http"

"github.com/kossiitkgp/kwoc-backend/v2/middleware"
Expand Down Expand Up @@ -32,6 +33,7 @@ type OAuthResBodyFields struct {

const OAUTH_TYPE_STUDENT string = "student"
const OAUTH_TYPE_MENTOR string = "mentor"
const OAUTH_TYPE_ORGANISER string = "organiser"

// OAuth godoc
//
Expand Down Expand Up @@ -80,6 +82,36 @@ func OAuth(w http.ResponseWriter, r *http.Request) {
return
}

// Check if the user is a organiser

isOrganiser := utils.IsUserExecutive(accessToken, userInfo.Username)
if isOrganiser {
fmt.Println("Is organiser: ", isOrganiser)
// Generate a mentor profile for a organiser
utils.GenMentorOrganiser(w, r, db, userInfo)

jwtString, err := utils.GenerateLoginJwtString(utils.LoginJwtFields{
Username: userInfo.Username,
UserType: OAUTH_TYPE_ORGANISER,
})
if err != nil {
utils.LogErrAndRespond(r, w, err, "Error generating a JWT string.", http.StatusInternalServerError)
return
}

resFields := OAuthResBodyFields{
Username: userInfo.Username,
Name: userInfo.Name,
Email: userInfo.Email,
College: "",
Type: OAUTH_TYPE_ORGANISER,
Jwt: jwtString,
}

utils.RespondWithJson(r, w, resFields)
return
}

// Check if the user has already registered
var isNewUser bool = true
var userType string = reqFields.Type
Expand Down Expand Up @@ -115,6 +147,7 @@ func OAuth(w http.ResponseWriter, r *http.Request) {
// Generate a JWT string for the user
jwtString, err := utils.GenerateLoginJwtString(utils.LoginJwtFields{
Username: userInfo.Username,
UserType: userType,
})
if err != nil {
utils.LogErrAndRespond(r, w, err, "Error generating a JWT string.", http.StatusInternalServerError)
Expand Down
82 changes: 82 additions & 0 deletions controllers/organiser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package controllers

import (
"fmt"
"net/http"
"strings"

"github.com/kossiitkgp/kwoc-backend/v2/middleware"
"github.com/kossiitkgp/kwoc-backend/v2/models"
"github.com/kossiitkgp/kwoc-backend/v2/utils"
)

type AcceptRejectProject struct {
// Id of the project in the database (required)
Id uint `json:"id"`
// Status to be set of the project
ProjectStatus bool `json:"project_status"`
// Status Remark to be set of the project
StatusRemark string `json:"status_remark"`
}

type ProjectOrg struct {
Bikram-ghuku marked this conversation as resolved.
Show resolved Hide resolved
ProjectStatus bool `json:"project_status"`
StatusRemark string `json:"status_remark"`
Project
}

func newProjectOrg(dbProject *models.Project) ProjectOrg {
tags := make([]string, 0)
if len(dbProject.Tags) != 0 {
tags = strings.Split(dbProject.Tags, ",")
}

return ProjectOrg{
Project: Project{
Id: dbProject.ID,
Name: dbProject.Name,
Description: dbProject.Description,
Tags: tags,
RepoLink: dbProject.RepoLink,
CommChannel: dbProject.CommChannel,
ReadmeLink: dbProject.ReadmeLink,
Mentor: newMentor(&dbProject.Mentor),
SecondaryMentor: newMentor(&dbProject.SecondaryMentor),
},
ProjectStatus: dbProject.ProjectStatus,
StatusRemark: dbProject.StatusRemark,
}
}

func OrgFetchAllProjectDetails(w http.ResponseWriter, r *http.Request) {
app := r.Context().Value(middleware.APP_CTX_KEY).(*middleware.App)
db := app.Db
user_details := r.Context().Value(middleware.LOGIN_CTX_USERNAME_KEY).(utils.LoginJwtFields)

if user_details.UserType != "organiser" {
utils.LogErrAndRespond(r, w, nil, fmt.Sprintf("Error '%s' is not an organiser", user_details.Username), 400)
return
}

var projects []models.Project

tx := db.
Table("projects").
Preload("Mentor").
Preload("SecondaryMentor").
Select("id", "name", "description", "tags", "repo_link", "comm_channel", "readme_link", "mentor_id", "secondary_mentor_id", "project_status", "status_remark", "pull_count").
Find(&projects)

if tx.Error != nil {
utils.LogErrAndRespond(r, w, tx.Error, "Error fetching projects from the database.", http.StatusInternalServerError)
return
}

var response []ProjectOrg = make([]ProjectOrg, 0)

for _, project := range projects {
response = append(response, newProjectOrg(&project))
}

utils.RespondWithJson(r, w, response)
}
19 changes: 13 additions & 6 deletions controllers/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,21 @@ func FetchProfile(w http.ResponseWriter, r *http.Request) {
app := r.Context().Value(middleware.APP_CTX_KEY).(*middleware.App)
db := app.Db

username := r.Context().Value(middleware.LOGIN_CTX_USERNAME_KEY).(string)
user_details := r.Context().Value(middleware.LOGIN_CTX_USERNAME_KEY).(utils.LoginJwtFields)

// Check if the student already exists in the db
student := models.Student{}
tx := db.
Table("students").
Where("username = ?", username).
Where("username = ?", user_details.Username).
First(&student)

if tx.Error != nil && tx.Error != gorm.ErrRecordNotFound {
utils.LogErrAndRespond(r, w, tx.Error, "Database error.", http.StatusInternalServerError)
return
}

student_exists := student.Username == username
student_exists := student.Username == user_details.Username
if student_exists {
utils.RespondWithJson(r, w, ProfileResBodyFields{
Username: student.Username,
Expand All @@ -64,20 +64,27 @@ func FetchProfile(w http.ResponseWriter, r *http.Request) {
mentor := models.Mentor{}
tx = db.
Table("mentors").
Where("username = ?", username).
Where("username = ?", user_details.Username).
First(&mentor)
if tx.Error != nil && tx.Error != gorm.ErrRecordNotFound {
utils.LogErrAndRespond(r, w, tx.Error, "Database error.", http.StatusInternalServerError)
return
}
mentor_exists := mentor.Username == username
mentor_exists := mentor.Username == user_details.Username

if mentor_exists {

userType := "mentor"

if user_details.UserType == OAUTH_TYPE_ORGANISER {
userType = OAUTH_TYPE_ORGANISER
}

utils.RespondWithJson(r, w, ProfileResBodyFields{
Username: mentor.Username,
Name: mentor.Name,
Email: mentor.Email,
Type: "mentor",
Type: userType,
})
return
}
Expand Down
2 changes: 1 addition & 1 deletion controllers/project_fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func FetchProjectDetails(w http.ResponseWriter, r *http.Request) {
app := r.Context().Value(middleware.APP_CTX_KEY).(*middleware.App)
db := app.Db

login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY))
login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY)).(utils.LoginJwtFields).Username

project := models.Project{}
tx := db.
Expand Down
4 changes: 2 additions & 2 deletions controllers/project_reg.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ func RegisterProject(w http.ResponseWriter, r *http.Request) {
return
}

login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY))
login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY)).(utils.LoginJwtFields).Username

err = utils.DetectSessionHijackAndRespond(r, w, reqFields.MentorUsername, login_username.(string), "Login username and mentor username do not match.")
err = utils.DetectSessionHijackAndRespond(r, w, reqFields.MentorUsername, login_username, "Login username and mentor username do not match.")
if err != nil {
return
}
Expand Down
54 changes: 35 additions & 19 deletions controllers/project_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ type UpdateProjectReqFields struct {
CommChannel string `json:"comm_channel"`
// Link to the project's README file
ReadmeLink string `json:"readme_link"`
// Status to be set of the project
ProjectStatus bool `json:"project_status"`
// Status Remark to be set of the project
StatusRemark string `json:"status_remark"`
}

// UpdateProject godoc
Expand Down Expand Up @@ -67,11 +71,13 @@ func UpdateProject(w http.ResponseWriter, r *http.Request) {
return
}

login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY))
login_details := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY)).(utils.LoginJwtFields)

err = utils.DetectSessionHijackAndRespond(r, w, reqFields.MentorUsername, login_username.(string), "Login username and mentor username do not match.")
if err != nil {
return
if login_details.UserType != OAUTH_TYPE_ORGANISER {
err = utils.DetectSessionHijackAndRespond(r, w, reqFields.MentorUsername, login_details.Username, "Login username and mentor username do not match.")
if err != nil {
return
}
}

// Check if the project already exists
Expand Down Expand Up @@ -99,12 +105,12 @@ func UpdateProject(w http.ResponseWriter, r *http.Request) {
return
}

if project.Mentor.Username != login_username {
if project.Mentor.Username != login_details.Username && login_details.UserType != OAUTH_TYPE_ORGANISER {
utils.LogErrAndRespond(
r,
w,
tx.Error,
fmt.Sprintf("Error: Mentor `%s` does not own the project with ID `%d`.", login_username, project.ID),
fmt.Sprintf("Error: Mentor `%s` does not own the project with ID `%d`.", login_details.Username, project.ID),
http.StatusBadRequest,
)
return
Expand Down Expand Up @@ -138,20 +144,30 @@ func UpdateProject(w http.ResponseWriter, r *http.Request) {
}
}

updatedProj := &models.Project{
Name: reqFields.Name,
Description: reqFields.Description,
Tags: strings.Join(reqFields.Tags, ","),
RepoLink: reqFields.RepoLink,
CommChannel: reqFields.CommChannel,
ReadmeLink: reqFields.ReadmeLink,
SecondaryMentor: secondaryMentor,
}
if login_details.UserType == OAUTH_TYPE_ORGANISER {

updateDet := map[string]interface{}{"status_remark": reqFields.StatusRemark, "project_status": reqFields.ProjectStatus}
tx = db.
Table("projects").
Where("id = ?", reqFields.Id).
Updates(updateDet)

} else {
updatedProj := &models.Project{
Name: reqFields.Name,
Description: reqFields.Description,
Tags: strings.Join(reqFields.Tags, ","),
RepoLink: reqFields.RepoLink,
CommChannel: reqFields.CommChannel,
ReadmeLink: reqFields.ReadmeLink,
SecondaryMentor: secondaryMentor,
}

tx = db.
Table("projects").
Where("id = ?", reqFields.Id).
Updates(updatedProj)
tx = db.
Table("projects").
Where("id = ?", reqFields.Id).
Updates(updatedProj)
}

if tx.Error != nil {
utils.LogErrAndRespond(r, w, tx.Error, "Error updating the project.", http.StatusInternalServerError)
Expand Down
10 changes: 5 additions & 5 deletions controllers/student.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func RegisterStudent(w http.ResponseWriter, r *http.Request) {
}

// Check if the JWT login username is the same as the student's given username
login_username := r.Context().Value(middleware.LOGIN_CTX_USERNAME_KEY).(string)
login_username := r.Context().Value(middleware.LOGIN_CTX_USERNAME_KEY).(utils.LoginJwtFields).Username

err = utils.DetectSessionHijackAndRespond(r, w, reqFields.Username, login_username, "Login username and given username do not match.")
if err != nil {
Expand Down Expand Up @@ -174,7 +174,7 @@ func StudentBlogLink(w http.ResponseWriter, r *http.Request) {
}

// Check if the JWT login username is the same as the student's given username
login_username := r.Context().Value(middleware.LOGIN_CTX_USERNAME_KEY).(string)
login_username := r.Context().Value(middleware.LOGIN_CTX_USERNAME_KEY).(utils.LoginJwtFields).Username

err = utils.DetectSessionHijackAndRespond(r, w, reqFields.Username, login_username, "Login username and given username do not match.")
if err != nil {
Expand Down Expand Up @@ -287,7 +287,7 @@ func FetchStudentDashboard(w http.ResponseWriter, r *http.Request) {

var modelStudent models.Student

login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY))
login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY)).(utils.LoginJwtFields).Username
tx := db.
Table("students").
Where("username = ?", login_username).
Expand Down Expand Up @@ -323,7 +323,7 @@ func UpdateStudentDetails(w http.ResponseWriter, r *http.Request) {

var modelStudent models.Student

login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY))
login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY)).(utils.LoginJwtFields).Username
tx := db.
Table("students").
Where("username = ?", login_username).
Expand Down Expand Up @@ -373,7 +373,7 @@ func GetStudentDetails(w http.ResponseWriter, r *http.Request) {
app := r.Context().Value(middleware.APP_CTX_KEY).(*middleware.App)
db := app.Db

login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY))
login_username := r.Context().Value(middleware.LoginCtxKey(middleware.LOGIN_CTX_USERNAME_KEY)).(utils.LoginJwtFields).Username

student := models.Student{}
tx := db.
Expand Down
2 changes: 1 addition & 1 deletion middleware/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func WithLogin(inner http.HandlerFunc) http.HandlerFunc {
}

reqContext := r.Context()
newContext := context.WithValue(reqContext, LoginCtxKey(LOGIN_CTX_USERNAME_KEY), claims.LoginJwtFields.Username)
newContext := context.WithValue(reqContext, LoginCtxKey(LOGIN_CTX_USERNAME_KEY), claims.LoginJwtFields)

inner.ServeHTTP(w, r.WithContext(newContext))
})
Expand Down
Loading
Loading