Skip to content

Commit

Permalink
Merge pull request #62 from SakshamSahgal/61-add-a-user-actvity-log-f…
Browse files Browse the repository at this point in the history
…eature

61 add a user actvity log feature
  • Loading branch information
SakshamSahgal authored Feb 5, 2024
2 parents f9ac937 + 5122d9b commit 1170163
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 28 deletions.
89 changes: 89 additions & 0 deletions ServerSide/Admin/Analytics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const axios = require('axios');

//function to get the browser information Object
function getBrowser(browser) {

let browserInfo = {
name: browser
}

// console.log(browser)

// if (fs.existsSync(path.join(__dirname, "..", "ClientSide", "Static", "GUI", "Browser", browser + ".png")))
// browserInfo.logo = path.join("GUI", "Browser", browser + ".png")
// else
// browserInfo.logo = path.join("GUI", "Browser", "default.png")

return browserInfo;
}

function getOS(os) {

let osInfo = {
name: os.os
}

// console.log(os)


// if (os.isAndroid)
// osInfo.logo = path.join("GUI", "OS", "Android.png")
// else if (os.isWindows)
// osInfo.logo = path.join("GUI", "OS", "Windows.png")
// else if (os.isLinux || os.isLinux64)
// osInfo.logo = path.join("GUI", "OS", "Linux.png")
// else if (os.isMac)
// osInfo.logo = path.join("GUI", "OS", "Mac.png")
// else if (os.isIOS)
// osInfo.logo = path.join("GUI", "OS", "IOS.png")
// else
// osInfo.logo = path.join("GUI", "OS", "Default.png")

return osInfo;
}

function getDeviceType(userAgentInfo) {

DeviceTypeInfo = {
}

if (userAgentInfo.isMobile) {
DeviceTypeInfo.name = "Mobile"
// DeviceTypeInfo.logo = path.join("GUI", "DeviceType", "Mobile.png")
} else if (userAgentInfo.isTablet) {
DeviceTypeInfo.name = "Tablet"
// DeviceTypeInfo.logo = path.join("GUI", "DeviceType", "Tablet.png")
} else if (userAgentInfo.isDesktop) {
DeviceTypeInfo.name = "Desktop"
// DeviceTypeInfo.logo = path.join("GUI", "DeviceType", "Desktop.png")
} else {
DeviceTypeInfo.name = "Unknown"
// DeviceTypeInfo.logo = path.join("GUI", "DeviceType", "Default.png")
}

return DeviceTypeInfo;
}

const getUserLocation = async (ip) => {

const ipAddress = ip; //IPv6-mapped IPv4 address
console.log("IP : ")
console.log(ipAddress);
const ipv4Address = ipAddress.split(':').pop();
console.log(ipAddress + " " + ipv4Address);

try {
const response = await axios.get(`https://ipinfo.io/${ipv4Address}/json`);
const locationData = response.data;
console.log(locationData)
locationData.latitude = locationData.loc.split(',')[0];
locationData.longitude = locationData.loc.split(',')[1];
return locationData;
} catch (error) {
// console.error(error);
console.log("req failed")
return null;
}
};

module.exports = { getBrowser, getOS, getDeviceType, getUserLocation };
31 changes: 31 additions & 0 deletions ServerSide/Admin/UserActivty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const { getBrowser, getOS, getDeviceType, getUserLocation } = require('./Analytics');

// This module is used to log user activity
async function GetUserActivity(req) {
// const userActivity = {
// timestamp: new Date(),
// method: req.method,
// url: req.url,
// headers: req.rawHeaders,
// clientIP: req.socket.remoteAddress,
// isAuthenticated: req.isAuthenticated(),
// userId: req.user ? req.user.id : null,
// userName: req.user ? req.user.displayName : null,
// // Add other relevant information as needed
// };
// console.log(userActivity);
// Access user agent information from req.useragent
const userAgentInfo = req.useragent;
// console.log(userAgentInfo);

let template = {
browserInfo: getBrowser(userAgentInfo.browser),
osInfo: getOS(userAgentInfo),
ip: req.ip,
deviceTypeInfo: getDeviceType(userAgentInfo),
locationData: await getUserLocation(req.ip)
}
console.log(template);
}

module.exports = { GetUserActivity };
2 changes: 1 addition & 1 deletion ServerSide/Middlewares.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const {writeDB,readDB,updateDB,deleteDB} = require("./MongoOperations.js"); //including the MongoOperations.js file (for the DB operations)
const {readDB,updateDB} = require("./MongoOperations.js"); //including the MongoOperations.js file (for the DB operations)

function isLoggedIn(req, res, next) { //Middleware to check if user is logged in
if (req.user) //check if user is authenticated
Expand Down
19 changes: 11 additions & 8 deletions ServerSide/MongoOperations.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,19 @@ const client = new MongoClient(process.env.URI, {
}
});

async function connectDB() {
try {
await client.connect();
console.log("Connected to the database");
} catch (error) {
console.error("Error:", error);
throw error; // Rethrow the error for the caller to handle
}
}


async function writeDB(Database, Collection, Data) { //Create Entry
try {
await client.connect();
const db = client.db(Database);
const collection = db.collection(Collection);

Expand All @@ -29,7 +38,6 @@ async function writeDB(Database, Collection, Data) { //Create Entry

async function readDB(Database, Collection, Query) { //Read Entry
try {
await client.connect();
const db = client.db(Database);
const collection = db.collection(Collection);

Expand All @@ -44,7 +52,6 @@ async function readDB(Database, Collection, Query) { //Read Entry

async function readwithSortDB(Database, Collection, FindQuery, SortQuerry) { //Read Entry
try {
await client.connect();
const db = client.db(Database);
const collection = db.collection(Collection);

Expand All @@ -59,7 +66,6 @@ async function readwithSortDB(Database, Collection, FindQuery, SortQuerry) { //R

async function updateDB(Database, Collection, FindQuery, UpdateQuery) { //Update Entry
try {
await client.connect();
const db = client.db(Database);
const collection = db.collection(Collection);

Expand All @@ -74,7 +80,6 @@ async function updateDB(Database, Collection, FindQuery, UpdateQuery) { //Update

async function deleteDB(Database, Collection, Query) { //Delete Entry
try {
await client.connect();
const db = client.db(Database);
const collection = db.collection(Collection);

Expand All @@ -89,7 +94,6 @@ async function deleteDB(Database, Collection, Query) { //Delete Entry

async function countDocuments(Database, Collection, Query) { //Count Entries
try {
await client.connect();
const db = client.db(Database);
const collection = db.collection(Collection);

Expand All @@ -105,7 +109,6 @@ async function countDocuments(Database, Collection, Query) { //Count Entries

async function SkipRead(Database, Collection, Query, sortQuery, Skip, Limit) { //Read Entry
try {
await client.connect();
const db = client.db(Database);
const collection = db.collection(Collection);

Expand All @@ -118,4 +121,4 @@ async function SkipRead(Database, Collection, Query, sortQuery, Skip, Limit) { /
}
}

module.exports = {writeDB, readDB, updateDB, deleteDB, countDocuments, SkipRead , readwithSortDB};
module.exports = {connectDB, writeDB, readDB, updateDB, deleteDB, countDocuments, SkipRead , readwithSortDB};
4 changes: 2 additions & 2 deletions ServerSide/PageRoutes/AnnouncementRoutes.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const { GetUserActivity } = require('../Admin/UserActivty.js');


module.exports = (app) => {
Expand All @@ -14,13 +15,12 @@ module.exports = (app) => {

app.get("/announcements/:page?", isLoggedIn, updateLastActivity, async (req, res) => {


var NoOfEntries = await countDocuments("Main","Announcements",{}) //Counting the number of entries in the database
var numberOfPage = Math.ceil(Number(NoOfEntries)/Number(process.env.limitPerPage)) //Calculating the number of pages
var curPage = (req.params.page == undefined) ? 1 : Math.max(Math.min(Number(req.params.page),numberOfPage),1) //Clamping the page number between 1 and 10
var toSkip = (curPage - 1) * Number(process.env.limitPerPage);

console.log(req.user.emails[0].value + " is viewing the announcements page " + curPage)
console.log(req.user.emails[0].value + " is viewing the announcements page " + curPage)
//console.log("No of Entries " , NoOfEntries, "numberOfPage ", numberOfPage, "curPage " , curPage,"toSkip " ,toSkip)

var coordinators = await readDB("Main", "Coordinators", { "list.gmail": req.user.emails[0].value }); //querrying DB to check if the email of the logged in user is present in the coordinators list
Expand Down
2 changes: 2 additions & 0 deletions ServerSide/PageRoutes/HomeRoutes.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const { GetUserActivity } = require("../Admin/UserActivty.js")

module.exports = (app) => {

Expand All @@ -8,6 +9,7 @@ module.exports = (app) => {

app.get("/home", isLoggedIn,updateLastActivity,async (req, res) => { //protected route

GetUserActivity(req)
console.log(req.user.emails[0].value + " is viewing the home page")

let Template = {
Expand Down
18 changes: 18 additions & 0 deletions ServerSide/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const express = require("express"); //including express package for creating a server
const session = require('express-session'); // Import express-session use to manage sessions
const path = require('path');
const useragent = require('express-useragent');

require('dotenv').config() //including the .env file (for the API keys and DB Credentials)

const app = express();

app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: true })); //telling express to use sesssion middleware [Secret used to sign the session cookie]
app.use(express.json({ limit: '1mb' })); //telling that my webapp will be sending/recieving data in json format (limiting to 1MB)
app.use(express.static(path.join(__dirname, "..", "ClientSide", "Static"))); //telling that my webapp will be using the files in the ClientSide/Static folder for static files

app.use(useragent.express()); // use the useragent middleware to parse useragent header
app.set('trust proxy', true); // Enable "trust proxy" to get the client's IP address through proxy headers [setting this makes the load balancer to forward the client's IP address in the X-Forwarded-For header instead of loopback address]
app.set('view engine', 'ejs'); // Setting the view engine to EJS

module.exports = { app };
24 changes: 7 additions & 17 deletions ServerSide/server.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
//------------------------------------------------------------Node Packages-----------------------------------------------------
const express = require("express"); //including express package for creating a server
const session = require('express-session'); // Import express-session use to manage sessions
const { app } = require("./app");
const path = require('path');
require('dotenv').config() //including the .env file (for the API keys and DB Credentials)

const app = express();

const port = process.env.DEV_PORT || 3000
const { redirectIfLoggedIn } = require("./Middlewares.js"); //including the Middlewares.js file (for the middlewares)
const { connectDB } = require("./MongoOperations.js");

app.use(session({ secret: process.env.SESSION_SECRET , resave: false, saveUninitialized: true })); //telling express to use sesssion middleware [Secret used to sign the session cookie]
app.use(express.json({limit : '1mb'})); //telling that my webapp will be sending/recieving data in json format (limiting to 1MB)
app.use(express.static(path.join(__dirname,"..","ClientSide","Static"))); //telling that my webapp will be using the files in the ClientSide/Static folder for static files

const {redirectIfLoggedIn} = require("./Middlewares.js"); //including the Middlewares.js file (for the middlewares)
//------------------------------------------------------------------------------------------------------------------------------

// Setting the view engine to EJS
app.set('view engine', 'ejs');

require("./Authorization/GoogleOAuthRoutes.js")(app); //requiring the GoogleOAuthRoutes.js file (for the google auth routes)
require("./PageRoutes/CoordinatorRoutes.js")(app); //requiring the CoordinatorRoutes.js file (for the coordinator page routes)
Expand All @@ -33,8 +21,10 @@ require("./KeepAlive.js")(app); //requiring t

app.listen(port, () => {
console.log("Server Started at port " + port);
connectDB();
});

app.get("/",redirectIfLoggedIn, (req, res) => { //unprotected route
//unprotected route
app.get("/",redirectIfLoggedIn, (req, res) => {
res.render(path.join(__dirname,"..","ClientSide","Knuth.ejs"));
});
});
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"ejs": "^3.1.9",
"express": "^4.18.2",
"express-session": "^1.17.3",
"express-useragent": "^1.0.15",
"imgur": "^0.3.1",
"mongodb": "^5.7.0",
"multer": "^1.4.5-lts.1",
Expand Down

0 comments on commit 1170163

Please sign in to comment.