Skip to content
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 3 additions & 15 deletions .github/scripts/generate-leaderboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ if (!GITHUB_TOKEN || !REPO_OWNER || !REPO_NAME) {
process.exit(1);
}

// GitHub API helper function
function apiRequest(path, page = 1) {
return new Promise((resolve, reject) => {
const options = {
Expand Down Expand Up @@ -74,7 +73,6 @@ function apiRequest(path, page = 1) {
});
}

// Fetch all pages of results
async function fetchAllPages(path) {
let allData = [];
let page = 1;
Expand All @@ -86,8 +84,7 @@ async function fetchAllPages(path) {
allData = allData.concat(response.data);
hasNextPage = response.hasNextPage;
page++;

// Add a small delay to respect rate limits

if (hasNextPage) {
await new Promise(resolve => setTimeout(resolve, 100));
}
Expand All @@ -103,21 +100,18 @@ async function fetchAllPages(path) {
async function generateLeaderboard() {
try {
console.log('Fetching closed issues with level labels...');

// Fetch closed issues with level labels

const issues = await fetchAllPages(`/repos/${REPO_OWNER}/${REPO_NAME}/issues?state=closed`);

console.log(`Found ${issues.length} closed issues`);

// Filter issues by level labels and extract assignee data
const levelIssues = issues.filter(issue => {
const labels = issue.labels.map(label => label.name.toLowerCase());
return labels.some(label => ['level1', 'level2', 'level3', 'level 1', 'level 2', 'level 3'].includes(label));
});

console.log(`Found ${levelIssues.length} closed issues with level labels`);

// Debug: Print some sample issues for troubleshooting

if (levelIssues.length > 0) {
console.log('Sample level issues found:');
levelIssues.slice(0, 3).forEach(issue => {
Expand All @@ -127,7 +121,6 @@ async function generateLeaderboard() {
});
}

// Build contributor stats
const contributorStats = {};

levelIssues.forEach(issue => {
Expand All @@ -146,7 +139,6 @@ async function generateLeaderboard() {
};
}

// Count level completions
if (labels.includes('level1') || labels.includes('level 1')) contributorStats[username].level1++;
if (labels.includes('level2') || labels.includes('level 2')) contributorStats[username].level2++;
if (labels.includes('level3') || labels.includes('level 3')) contributorStats[username].level3++;
Expand All @@ -155,7 +147,6 @@ async function generateLeaderboard() {

console.log(`Processing ${Object.keys(contributorStats).length} contributors...`);

// Fetch merged PRs for each contributor
for (const username of Object.keys(contributorStats)) {
try {
console.log(`Fetching PRs for ${username}...`);
Expand All @@ -173,7 +164,6 @@ async function generateLeaderboard() {
}
}

// Generate leaderboard markdown
let leaderboard = `# 🏆 Contributors Leaderboard

This leaderboard tracks contributors who have completed issues labeled as \`level1\`, \`level2\`, or \`level3\`, along with their merged pull requests.
Expand All @@ -184,7 +174,6 @@ This leaderboard tracks contributors who have completed issues labeled as \`leve
|----------|---------|---------|---------|-------------|
`;

// Sort contributors by total contributions (sum of all levels + PRs)
const sortedContributors = Object.entries(contributorStats)
.map(([username, stats]) => ({
username,
Expand Down Expand Up @@ -212,7 +201,6 @@ This leaderboard tracks contributors who have completed issues labeled as \`leve
*This leaderboard is automatically updated by GitHub Actions.*
`;

// Write to file
const fs = require('fs');
fs.writeFileSync('LEADERBOARD.md', leaderboard);

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
🚨 Please make sure you are sending pull requrest for 'master' branch.


# 📚 NotesVault - Academic Resource Management Platform

**NotesVault** is an open-source, full-stack web application designed to help **students**, **faculty**, and **academic institutions** efficiently store, browse, and manage academic notes, question papers, and educational resources. Built with modern technologies and inspired by platforms like RGPV Online, it provides a comprehensive solution for academic resource sharing.

---

## ✨ Key Features
## ✨ KEY FEATURES

### 📖 Core Functionality

Expand Down
50 changes: 44 additions & 6 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
# Security notes — NotesVault (local dev)

This repository currently contains a static frontend served from `pages/` and a small Flask backend under `backend/`.

Important security notes (what's implemented)
- Client-side checks: the frontend uses `localStorage` to store a `loggedInUser` object and client-side JavaScript checks redirect guests away from protected UI pages. These checks improve UX but are not a security boundary.

What's NOT protected (and why this matters)
- There is currently no server-side authentication or authorization. The Flask app does not validate requests or sessions. Any data or future API endpoints will be publicly accessible unless server-side checks are added.
- Client-side checks are trivial to bypass (browser DevTools, manipulating `localStorage`, or crafting direct HTTP requests).

Recommended next steps to harden the app
1. Implement server-side auth and sessions
- Add user authentication endpoints in the Flask backend (login/logout), and set a secure session cookie (use `flask-login` or signed cookies).
- Protect any API routes (uploads, profile updates, download endpoints) on the server by checking session or token.

2. Use secure cookies, not localStorage, for auth-sensitive tokens
- Store session identifiers in HttpOnly, Secure cookies. Avoid storing authentication tokens or passwords in `localStorage`.

3. Add HTTPS (TLS) in production
- Always serve the app over TLS in production (use a reverse proxy like nginx or deploy to a platform that terminates TLS).

4. Validate & authorize on the server for all actions
- Server must validate the authenticated user is allowed to perform requested actions (e.g., only owner can delete/edit a file).

5. Protect file uploads and downloads
- Validate file types and sizes, store uploads outside of webroot or use signed URLs, and scan for malware if relevant.

6. Rate-limiting, brute-force protection, and logging
- Add rate-limiting on auth endpoints, and log suspicious activity.

7. CORS and CSRF
- If you expose APIs to cross-origin clients, configure CORS carefully.
- Protect state-changing endpoints from CSRF (use SameSite cookies or CSRF tokens).

Quick dev notes
- For now, the frontend will keep using client-side checks for development UX. Treat these as convenience features, not security controls.
- If you want, I can implement a minimal Flask session-based auth flow next (login route, protected endpoints, and cookie-based sessions).
# 🔒 Security Policy

## 📅 Supported Versions
Expand All @@ -16,14 +54,14 @@ If you find a security issue or vulnerability in **NotesVault**, please report i

### 🔐 How to Report

- Open a GitHub [Issue](https://github.com/opensource-society/NotesVault/issues) with `[SECURITY]` in the title, OR
- Open a GitHub [Issue](https://github.com/opensource-society/NotesVault/issues) with `[SECURITY]` in the title, OR
- Contact a maintainer directly via email

We will:

- Respond within 48–72 hours
- Investigate the report
- Work on a fix
- Respond within 48–72 hours
- Investigate the report
- Work on a fix
- Credit the responsible disclosure (optional)

---
Expand All @@ -32,8 +70,8 @@ We will:

Please avoid:

- Publicly disclosing the vulnerability before it's fixed
- Testing attacks on active users
- Publicly disclosing the vulnerability before it's fixed
- Testing attacks on active users
- Exploiting the issue for personal or public gain

---
Expand Down
Loading