Intelligent Question Paper Search
Website
·
Report Bug / Request Feature
·
Backend Documentation
Table of Contents
IQPS is a platform for searching and uploading previous year question papers for IIT Kharagpur students. The frontend is deployed at https://qp.metakgp.org and the backend is hosted on a DigitalOcean droplet with 2GB RAM and a single CPU. See MetaPloy for the deployment architecture. IQPS was originally created by Shubham Mishra in python. You can find it here.
Note
Currently in active development. Get involved at our Slack.
- Clone this repository.
- For starting the backend:
- Change directory to backend
cd backend - Make the env file by copying the template:
cp .env.template .env - Fill the env variables and set
DB_HOST=localhostfor running locally for development (see Environment Variables). Make sure to create corresponding folders forSTATIC_FILE_STORAGE_LOCATION,UPLOADED_QPS_PATH, andLIBRARY_QPS_PATH. - Set up the database (see Database)
- Start the Rust backend by running
cargo run .
- Change directory to backend
- Set up the frontend by running
pnpm installand thenpnpm startin thefrontend/directory. - (Optional) Set up an http file server for serving static files from the
STATIC_FILE_STORAGE_LOCATIONdirectory. (eg:python3 -m http.server 8081) The host of this server should be set in the.envfile asSTATIC_FILES_URL. - Profit.
To initialise the database for the first time:
- Set environment variables for Postgres in the
.envfile. - Start the database by running
docker compose -f docker-compose.dev.yaml up -d. - Initialise the database:
- Open a shell in the docker container by running
docker compose -f docker-compose.dev.yaml exec database-dev bash. - Connect to the database by running
psql -U $POSTGRES_USER -d $POSTGRES_DB. - Run the queries in
INIT_DBinbackend/src/db/queries.rsto initialise the database.
- Open a shell in the docker container by running
To run the pre-initialised database:
- Start the database by running
docker compose -f docker-compose.dev.yaml up -d.
For Production:
- Set environment variables for Postgres in the
.envfile. - Start the database by running
docker compose -f docker-compose.yaml up -d. - Initialise the database:
- Open a shell in the docker container by running
docker compose -f docker-compose.yaml exec iqps-backend bash. - Connect to the database by running
psql -U $POSTGRES_USER -d $POSTGRES_DB. - Run the queries in
INIT_DBinbackend/src/db/queries.rsto initialise the database.
- Open a shell in the docker container by running
IQPS uses GitHub OAuth for authentication to the /admin page. To set up authentication:
- Create a new OAuth app on GitHub.
- Go to https://github.com/settings/developers and create a new OAuth app.
- Set the Homepage URL to
http://localhost:5173and Authorization callback URL tohttp://localhost:5173/oauth. - Once created, generate a client secret. Copy the client ID and secret into the
.envfile.
- Set the Authentication environment variables in the
.envfile.
For Production:
- Create a new OAuth app on GitHub. (Should be from the same GitHub account as the organization)
- Go to https://github.com/settings/developers and create a new OAuth app.
- Set the Homepage URL to
<prod-url>and Authorization callback URL to<prod-url>/oauth. - Once created, generate a client secret. Add the client ID and secret to environment variables.
- Set the Authentication environment variables.
- Github OAuth documentation: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
On visiting /admin, if the user is not logged in, they get redirected to the GitHub OAuth page. After the user logs in, GitHub redirects them back to our /oauth endpoint with a code. The backend then uses this code to fetch an access token and username. The username is then checked against the allowed admins. If so, a JWT token is generated with the user's username and sent back to the frontend. The frontend then stores this token in local storage and sends it with every request to the backend. The backend verifies this token and allows access to admin functions.
A user is considered as an admin if they are a part of the team GH_ORG_TEAM_SLUG in GH_ORG_NAME, or if their username is in the GH_ADMIN_USERNAMES list.
The crawler is a go script which crawls and downloads papers from peqp (only accessible over campus network) and spits an archive which can be imported into the database.
- Change directory to
crawler/and rungo mod tidy. - Run the crawler by running
go run crawler.go [flags]. (Make sure you are connected to the campus network) (Rungo run crawler.go -hto see flags that can be set.) - This will generate a
qp.tar.gzfile. Transfer this file to the server'sbackend/folder. - (Development): In the backend, run
cargo run --bin import-papers qp.tar.gzto import the data into the database. (Make sure the database is set up and running)
(Production): In the backend, run./import_papers.sh ./qp.tar.gzto run the import script in the docker container running the application.
- Set up MetaPloy for production.
- Clone this repository at a convenient location such as
/deployments. cd backend/- Set the appropriate production environment variables in the
.envfile. - Run
docker compose upto start the backend. - Optionally set up a Systemd service to start IQPS on startup or use this deployment github workflow.
Environment variables can be set using a .env file. Use the .env.template files for reference. See backend/src/env.rs for more documentation and types.
DB_NAME: Database nameDB_HOST: Database hostname (eg:localhost)DB_PORT: Database portDB_USER: Database usernameDB_PASSWORD: Database password
GH_CLIENT_ID: Client ID of the Github OAuth app.GH_CLIENT_SECRET: Client secret of the Github OAuth app.GH_ORG_NAME: The name of the Github organization of the admins.GH_ORG_TEAM_SLUG: The URL slug of the Github org team of the admins.GH_ORG_ADMIN_TOKEN: Github token of organization admin (withread:orgscope).GH_ADMIN_USERNAMES: Comma separated list of Github usernames of the admins. (other than the org team members)JWT_SECRET: A secret key/password for JWT signing. It should be a long, random, unguessable string.
SLACK_WEBHOOK_URL: URL of Slack webhook for sending notifications (ignored if empty).MAX_UPLOAD_LIMIT: Maximum number of files that can be uploaded at once.LOG_LOCATION: The path to a local logfile.STATIC_FILES_URL: The URL of the static files server. (eg:https://static.metakgp.org)STATIC_FILE_STORAGE_LOCATION: The path to the local directory from which the static files are served.UPLOADED_QPS_PATH: A path relative toSTATIC_FILE_STORAGE_LOCATIONwhere the uploaded question papers will be stored. (eg:iqps/uploaded)LIBRARY_QPS_PATH: A path relative toSTATIC_FILE_STORAGE_LOCATIONwhere the library question papers are scraped and stored. (eg:peqp/qp)SERVER_PORT: The port on which the server listens.CORS_ALLOWED_ORIGINS: A comma (,) separated list of origins to be allowed in CORS.
VITE_BACKEND_URL: The IQPS backend URL. Usehttp://localhost:8080in development.VITE_MAX_UPLOAD_LIMITThe maximum number of files that can be uploaded at once. (Note: This is only a client-side limit)VITE_GH_OAUTH_CLIENT_IDThe Client ID of the Github OAuth app.
The currently active maintainer(s) of this project. See https://wiki.metakgp.org/w/Metakgp:Project_Maintainer.
Previous maintainer(s) of this project. See https://wiki.metakgp.org/w/Metakgp:Project_Maintainer.
Honoring the original creator(s) and ideator(s) of this project.
