Skip to content

Commit

Permalink
add all papers endpoint
Browse files Browse the repository at this point in the history
Signed-off-by: Rajiv Harlalka <[email protected]>
  • Loading branch information
rajivharlalka authored and harshkhandeparkar committed Sep 16, 2024
1 parent d287b02 commit 386b12d
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 40 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ qp.tar.xz
go.work.sum

frontend/public/pdf.worker.min.mjs
*.log
*.log
*.patch
49 changes: 33 additions & 16 deletions backend/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/jackc/pgx/v5"
"github.com/metakgp/iqps/backend/pkg/config"
"github.com/metakgp/iqps/backend/pkg/db"
"github.com/metakgp/iqps/backend/pkg/models"
"github.com/metakgp/iqps/backend/query"
)

Expand All @@ -44,7 +45,7 @@ func HandleHealthCheck(w http.ResponseWriter, r *http.Request) {

func HandleQPYear(w http.ResponseWriter, r *http.Request) {
db := db.GetDB()
result := db.QueryRow(context.Background(), "SELECT MIN(year), MAX(year) FROM iqps")
result := db.Db.QueryRow(context.Background(), "SELECT MIN(year), MAX(year) FROM iqps")
var minYear, maxYear int
err := result.Scan(&minYear, &maxYear)
if err != nil {
Expand All @@ -58,16 +59,16 @@ func HandleQPYear(w http.ResponseWriter, r *http.Request) {

func HandleLibraryPapers(w http.ResponseWriter, r *http.Request) {
db := db.GetDB()
rows, err := db.Query(context.Background(), "SELECT id, course_code, course_name, year, exam, filelink, from_library FROM iqps WHERE from_library = 'true'")
rows, err := db.Db.Query(context.Background(), "SELECT id, course_code, course_name, year, exam, filelink, from_library FROM iqps WHERE from_library = 'true'")
if err != nil {
sendErrorResponse(w, http.StatusInternalServerError, "Could not Query Question Paper, Try Later!", nil)
return
}
defer rows.Close()

var qps []QuestionPaper = make([]QuestionPaper, 0)
var qps []models.QuestionPaper = make([]models.QuestionPaper, 0)
for rows.Next() {
qp := QuestionPaper{}
qp := models.QuestionPaper{}
err := rows.Scan(&qp.ID, &qp.CourseCode, &qp.CourseName, &qp.Year, &qp.Exam, &qp.FileLink, &qp.FromLibrary)
if err != nil {
sendErrorResponse(w, http.StatusInternalServerError, "error parsing question paper details, contact admin ", nil)
Expand Down Expand Up @@ -103,16 +104,16 @@ func HandleQPSearch(w http.ResponseWriter, r *http.Request) {
}
}

rows, err := db.Query(context.Background(), query, params)
rows, err := db.Db.Query(context.Background(), query, params)
config.Get().Logger.Debug("rows were fetched")
if err != nil {
sendErrorResponse(w, http.StatusInternalServerError, err.Error(), nil)
return
}
defer rows.Close()
var qps []QuestionPaper = make([]QuestionPaper, 0)
var qps []models.QuestionPaper = make([]models.QuestionPaper, 0)
for rows.Next() {
qp := QuestionPaper{}
qp := models.QuestionPaper{}
err := rows.Scan(&qp.ID, &qp.CourseCode, &qp.CourseName, &qp.Year, &qp.Exam, &qp.FileLink, &qp.FromLibrary, &qp.UploadTimestamp, &qp.ApproveStatus)
if err != nil {
config.Get().Logger.Error("HandleQPSearch: Error parsing question paper details")
Expand All @@ -130,18 +131,31 @@ func HandleQPSearch(w http.ResponseWriter, r *http.Request) {
sendResponse(w, http.StatusOK, qps)
}

func ListAllPapers(w http.ResponseWriter, r *http.Request) {
db := db.GetDB()

qps, err := db.FetchAllQuestionPapers()
if err != nil {
sendErrorResponse(w, http.StatusInternalServerError, err.Error(), nil)
return
}

config.Get().Logger.Info("listUnapprovedPapers: Unapproved Question paper count: ", len(qps))
sendResponse(w, http.StatusOK, qps)
}

func ListUnapprovedPapers(w http.ResponseWriter, r *http.Request) {
db := db.GetDB()
rows, err := db.Query(context.Background(), "SELECT course_code, course_name, year, exam,filelink,id, from_library FROM iqps WHERE approve_status = false ORDER BY upload_timestamp ASC")
rows, err := db.Db.Query(context.Background(), "SELECT course_code, course_name, year, exam,filelink,id, from_library FROM iqps WHERE approve_status = false ORDER BY upload_timestamp ASC")
if err != nil {
sendErrorResponse(w, http.StatusInternalServerError, err.Error(), nil)
return
}
defer rows.Close()

var qps []QuestionPaper = make([]QuestionPaper, 0)
var qps []models.QuestionPaper = make([]models.QuestionPaper, 0)
for rows.Next() {
qp := QuestionPaper{}
qp := models.QuestionPaper{}
err := rows.Scan(&qp.CourseCode, &qp.CourseName, &qp.Year, &qp.Exam, &qp.FileLink, &qp.ID, &qp.FromLibrary)
if err != nil {
sendErrorResponse(w, http.StatusInternalServerError, err.Error(), nil)
Expand All @@ -159,7 +173,7 @@ func HandleFileUpload(w http.ResponseWriter, r *http.Request) {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
var response []uploadEndpointRes = make([]uploadEndpointRes, 0)
var response []models.UploadEndpointRes = make([]models.UploadEndpointRes, 0)
// Max total size of 50MB
const MaxBodySize = 50 << 20 // 1<<20 = 1024*1024 = 1MB
r.Body = http.MaxBytesReader(w, r.Body, MaxBodySize)
Expand All @@ -182,7 +196,7 @@ func HandleFileUpload(w http.ResponseWriter, r *http.Request) {
}

for _, fileHeader := range files {
resp := uploadEndpointRes{Filename: fileHeader.Filename, Status: "success"}
resp := models.UploadEndpointRes{Filename: fileHeader.Filename, Status: "success"}

if fileHeader.Size > 10<<20 {
config.Get().Logger.Errorf("HandleFileUpload: File of size %d uploaded", fileHeader.Size)
Expand Down Expand Up @@ -297,15 +311,15 @@ func populateDB(filename string) error {
fileLink := filepath.Join(config.Get().UploadedQPsPath, filename+".pdf")
query := "INSERT INTO iqps (course_code, course_name, year, exam, filelink, from_library) VALUES ($1, $2, $3, $4, $5, $6);"

_, err := db.Exec(context.Background(), query, courseCode, courseName, year, exam, fileLink, fromLibrary)
_, err := db.Db.Exec(context.Background(), query, courseCode, courseName, year, exam, fileLink, fromLibrary)
if err != nil {
return fmt.Errorf("failed to add qp to database: %v", err.Error())
}
return nil
}

func GhAuth(w http.ResponseWriter, r *http.Request) {
ghOAuthReqBody := GhOAuthReqBody{}
ghOAuthReqBody := models.GhOAuthReqBody{}
if err := json.NewDecoder(r.Body).Decode(&ghOAuthReqBody); err != nil {
sendErrorResponse(w, http.StatusBadRequest, err.Error(), nil)
return
Expand All @@ -332,7 +346,7 @@ func GhAuth(w http.ResponseWriter, r *http.Request) {
defer resp.Body.Close()

// Decode the response
var tokenResponse GithubAccessTokenResponse
var tokenResponse models.GithubAccessTokenResponse
if err := json.NewDecoder(resp.Body).Decode(&tokenResponse); err != nil {
fmt.Println("Error Decoding Github Access Token: ", err.Error())
sendErrorResponse(w, http.StatusInternalServerError, "Could not decode github token", nil)
Expand All @@ -352,7 +366,7 @@ func GhAuth(w http.ResponseWriter, r *http.Request) {
defer resp.Body.Close()

// Decode the response
var userResponse GithubUserResponse
var userResponse models.GithubUserResponse
if err := json.NewDecoder(resp.Body).Decode(&userResponse); err != nil {
fmt.Println("Error decoding username: ", err.Error())
sendErrorResponse(w, http.StatusInternalServerError, "Could not decode github token", nil)
Expand Down Expand Up @@ -411,6 +425,9 @@ func GhAuth(w http.ResponseWriter, r *http.Request) {
sendErrorResponse(w, http.StatusInternalServerError, "Error signing JWT token, try again later", nil)
return
}
var respData struct {
Token string `json:"token"`
}
respData.Token = tokenString

// Send the response
Expand Down
1 change: 1 addition & 0 deletions backend/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func main() {
http.HandleFunc("POST /upload", HandleFileUpload)
http.HandleFunc("POST /oauth", GhAuth)
http.Handle("GET /unapproved", JWTMiddleware(http.HandlerFunc(ListUnapprovedPapers)))
http.Handle("GET /all", JWTMiddleware(http.HandlerFunc(ListAllPapers)))

logger := config.Get().Logger
c := cors.New(cors.Options{
Expand Down
40 changes: 23 additions & 17 deletions backend/pkg/db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,54 +11,60 @@ import (
)

var (
database *pgxpool.Pool
mu sync.Mutex
database *db
)

type db struct {
Db *pgxpool.Pool
}

const init_db = `CREATE TABLE IF NOT EXISTS iqps (
id integer primary key generated always as identity,
course_code TEXT NOT NULL DEFAULT '',
course_name TEXT NOT NULL,
year INTEGER NOT NULL,
id integer primary key generated always as identity,
course_code TEXT NOT NULL DEFAULT '',
course_name TEXT NOT NULL,
year INTEGER NOT NULL,
exam TEXT CHECK (exam IN ('midsem', 'endsem') OR exam = ''),
filelink TEXT NOT NULL,
from_library BOOLEAN DEFAULT FALSE,
upload_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
approve_status BOOLEAN DEFAULT FALSE,
fts_course_details tsvector GENERATED ALWAYS AS (to_tsvector('english', course_code || ' ' || course_name)) stored
);
CREATE INDEX IF NOT EXISTS iqps_fts ON iqps USING gin (fts_course_details);
create index IF NOT EXISTS idx_course_name_trgm on iqps using gin (course_name gin_trgm_ops);
`
);
CREATE INDEX IF NOT EXISTS iqps_fts ON iqps USING gin (fts_course_details);
create index IF NOT EXISTS idx_course_name_trgm on iqps using gin (course_name gin_trgm_ops);
`

func InitDB() *pgxpool.Pool {
func InitDB() *db {
var err error
dbConfig := config.Get().DB
psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", dbConfig.Host, dbConfig.Port, dbConfig.Username, dbConfig.Password, dbConfig.DBname)
// database, err = sql.Open("postgres", psqlconn)
database, err = pgxpool.New(context.Background(), psqlconn)
var dbs *pgxpool.Pool
dbs, err = pgxpool.New(context.Background(), psqlconn)
if err != nil {
panic("Invalid Database connection string")
}

err = database.Ping(context.Background())
err = dbs.Ping(context.Background())
if err != nil {
panic("Database did not respond to ping")
}
fmt.Println("Database connected")
_, err = database.Exec(context.Background(), init_db)
_, err = dbs.Exec(context.Background(), init_db)
if err != nil {
log.Fatal("Error initializting database: ", err.Error())
}

config.Get().Logger.Info("Successfully connected to database")
database := &db{dbs}
return database
}

func GetDB() *pgxpool.Pool {
func GetDB() *db {
if database == nil {
mu.Lock()
defer mu.Unlock()
Expand Down
33 changes: 33 additions & 0 deletions backend/pkg/db/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package db

import (
"context"
"errors"
"fmt"

"github.com/metakgp/iqps/backend/pkg/config"
"github.com/metakgp/iqps/backend/pkg/models"
)

func (db *db) FetchAllQuestionPapers() ([]models.QuestionPaper, error) {
rows, err := db.Db.Query(context.Background(), "SELECT course_code,course_name,year,exam,filelink,id,from_library FROM iqps ORDER BY upload_timestamp ASC")
if err != nil {
config.Get().Logger.Errorf("FetchAllQuestionpapers: Could not fetch all question papers, error: %+v", err.Error())
return nil, errors.New("unable to fetch question paper, try again later")
}
defer rows.Close()

var qps []models.QuestionPaper = make([]models.QuestionPaper, 0)
for rows.Next() {
qp := models.QuestionPaper{}
err := rows.Scan(&qp.CourseCode, &qp.CourseName, &qp.Year, &qp.Exam, &qp.FileLink, &qp.ID, &qp.FromLibrary)
if err != nil {
config.Get().Logger.Errorf("FetchAllQuestionpapers: Error Scanning Paper in Struct, error: %+v", err.Error())
return nil, errors.New("unable to fetch question paper, try again later")
}
qp.FileLink = fmt.Sprintf("%s/%s", config.Get().StaticFilesUrl, qp.FileLink)
qps = append(qps, qp)
}

return qps, nil
}
8 changes: 2 additions & 6 deletions backend/model.go → backend/pkg/models/model.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package main
package models

import (
"github.com/jackc/pgx/v5/pgtype"
)

var respData struct {
Token string `json:"token"`
}

type QuestionPaper struct {
ID int `json:"id"`
CourseCode string `json:"course_code"`
Expand All @@ -21,7 +17,7 @@ type QuestionPaper struct {
CourseDetails string `json:"course_details,omitempty"`
}

type uploadEndpointRes struct {
type UploadEndpointRes struct {
Filename string `json:"filename"`
Status string `json:"status"`
Description string `json:"description"`
Expand Down

0 comments on commit 386b12d

Please sign in to comment.