-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 536a6a4
Showing
16 changed files
with
397 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Copy this file to .env and edit the settings | ||
|
||
# Port to listen on (example: 3000) | ||
PORT= | ||
|
||
# MongoDB database URL (example: mongodb://localhost/dbname) | ||
DATABASE_URL= | ||
|
||
# Session secret string (must be unique to your server) | ||
SESSION_SECRET= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
node_modules/ | ||
.gpt-pilot/ | ||
.env | ||
package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
const mongoose = require('mongoose'); | ||
const bcrypt = require('bcrypt'); | ||
const { v4: uuidv4 } = require('uuid'); | ||
|
||
const userSchema = new mongoose.Schema({ | ||
username: { type: String, unique: true, required: true }, | ||
password: { type: String, required: true }, | ||
apiKey: { type: String, unique: true } | ||
}); | ||
|
||
// Pre-save middleware for generating the API key and hashing the password | ||
userSchema.pre('save', async function(next) { | ||
const user = this; | ||
|
||
// Generating the API key | ||
if (user.isNew) { | ||
try { | ||
user.apiKey = uuidv4(); // Generate a unique API key | ||
console.log(`API Key generated for user: ${user.username}`); | ||
} catch (err) { | ||
console.error('Error generating API key:', err.message, err.stack); | ||
return next(err); | ||
} | ||
} | ||
|
||
// Hashing the password | ||
if (user.isModified('password')) { | ||
try { | ||
const hash = await bcrypt.hash(user.password, 10); | ||
user.password = hash; | ||
console.log(`Password hashed for user: ${user.username}`); | ||
} catch (err) { | ||
console.error('Error hashing password:', err.message, err.stack); | ||
return next(err); | ||
} | ||
} | ||
|
||
next(); | ||
}); | ||
|
||
const User = mongoose.model('User', userSchema); | ||
|
||
module.exports = User; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "GPTOptimizely", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "server.js", | ||
"scripts": { | ||
"start": "node server.js", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"bcrypt": "^5.1.1", | ||
"body-parser": "^1.20.2", | ||
"chart.js": "^4.4.1", | ||
"connect-flash": "^0.1.1", | ||
"connect-mongo": "^5.1.0", | ||
"csv-writer": "^1.6.0", | ||
"dotenv": "^16.4.1", | ||
"ejs": "^3.1.9", | ||
"express": "^4.18.2", | ||
"express-session": "^1.18.0", | ||
"moment": "^2.30.1", | ||
"mongoose": "^8.1.1", | ||
"uuid": "^9.0.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/* Placeholder for custom styles */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
// Placeholder for future JavaScript code |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const express = require('express'); | ||
const User = require('../models/User'); | ||
|
||
const router = express.Router(); | ||
|
||
router.get('/api/generate-snippet', async (req, res) => { | ||
const { apiKey } = req.query; | ||
if (!apiKey) { | ||
console.error('API key query parameter is missing.'); | ||
return res.status(400).send('API key is required.'); | ||
} | ||
|
||
try { | ||
const user = await User.findOne({ apiKey }); | ||
if (!user) { | ||
console.error(`Invalid API key: ${apiKey}`); | ||
return res.status(404).send('Invalid API key.'); | ||
} | ||
|
||
const snippet = `<script src="http://yourdomain.com/loader.js" data-api-key="${apiKey}"></script>`; // INPUT_REQUIRED {replace http://yourdomain.com/loader.js with your actual domain and path to the loader.js} | ||
console.log(`Snippet generated for API key: ${apiKey}`); | ||
res.type('text/plain').send(snippet); | ||
} catch (error) { | ||
console.error('Error generating snippet:', error.message, error.stack); | ||
res.status(500).send('Internal server error while generating snippet.'); | ||
} | ||
}); | ||
|
||
module.exports = router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
const express = require('express'); | ||
const User = require('../models/User'); | ||
const bcrypt = require('bcrypt'); | ||
const router = express.Router(); | ||
|
||
router.get('/auth/register', (req, res) => { | ||
res.render('register', { error: '' }); | ||
}); | ||
|
||
router.post('/auth/register', async (req, res) => { | ||
try { | ||
const { username, password } = req.body; | ||
const existingUser = await User.findOne({ username }); | ||
if (existingUser) { | ||
console.log('Username already exists:', username); | ||
return res.render('register', { error: 'Username already exists.' }); | ||
} | ||
await User.create({ username, password }); | ||
console.log('User registered successfully:', username); | ||
res.redirect('/auth/login'); | ||
} catch (error) { | ||
console.error('Registration error:', error.message, error.stack); | ||
res.render('register', { error: error.message }); | ||
} | ||
}); | ||
|
||
router.get('/auth/login', (req, res) => { | ||
res.render('login', { error: '' }); | ||
}); | ||
|
||
router.post('/auth/login', async (req, res) => { | ||
try { | ||
const { username, password } = req.body; | ||
const user = await User.findOne({ username }); | ||
if (!user) { | ||
console.log('User not found:', username); | ||
return res.render('login', { error: 'Invalid username or password.' }); | ||
} | ||
const isMatch = await bcrypt.compare(password, user.password); | ||
if (isMatch) { | ||
req.session.userId = user._id; | ||
console.log('User logged in successfully:', username); | ||
return res.redirect('/'); | ||
} else { | ||
console.log('Password is incorrect for user:', username); | ||
return res.render('login', { error: 'Invalid username or password.' }); | ||
} | ||
} catch (error) { | ||
console.error('Login error:', error.message, error.stack); | ||
res.render('login', { error: error.message }); | ||
} | ||
}); | ||
|
||
router.get('/auth/logout', (req, res) => { | ||
req.session.destroy(err => { | ||
if (err) { | ||
console.error('Error during session destruction:', err.message, err.stack); | ||
return res.status(500).send('Error logging out'); | ||
} | ||
console.log('User logged out successfully'); | ||
res.redirect('/auth/login'); | ||
}); | ||
}); | ||
|
||
module.exports = router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
const isAuthenticated = (req, res, next) => { | ||
if (req.session && req.session.userId) { | ||
return next(); // User is authenticated, proceed to the next middleware/route handler | ||
} else { | ||
return res.status(401).send('You are not authenticated'); // User is not authenticated | ||
} | ||
}; | ||
|
||
module.exports = { | ||
isAuthenticated | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Load environment variables | ||
require("dotenv").config(); | ||
const mongoose = require("mongoose"); | ||
const express = require("express"); | ||
const session = require("express-session"); | ||
const MongoStore = require('connect-mongo'); | ||
const authRoutes = require("./routes/authRoutes"); | ||
const apiRoutes = require('./routes/apiRoutes'); // Include API routes | ||
|
||
if (!process.env.DATABASE_URL || !process.env.SESSION_SECRET) { | ||
console.error("Error: config environment variables not set. Please create/edit .env configuration file."); | ||
process.exit(-1); | ||
} | ||
|
||
const app = express(); | ||
const port = process.env.PORT || 3000; | ||
|
||
// Middleware to parse request bodies | ||
app.use(express.urlencoded({ extended: true })); | ||
app.use(express.json()); | ||
|
||
// Setting the templating engine to EJS | ||
app.set("view engine", "ejs"); | ||
|
||
// Serve static files | ||
app.use(express.static("public")); | ||
|
||
// Database connection | ||
mongoose | ||
.connect(process.env.DATABASE_URL) | ||
.then(() => { | ||
console.log("Database connected successfully"); | ||
}) | ||
.catch((err) => { | ||
console.error(`Database connection error: ${err.message}`); | ||
console.error(err.stack); | ||
process.exit(1); | ||
}); | ||
|
||
// Session configuration with connect-mongo | ||
app.use( | ||
session({ | ||
secret: process.env.SESSION_SECRET, | ||
resave: false, | ||
saveUninitialized: false, | ||
store: MongoStore.create({ mongoUrl: process.env.DATABASE_URL }), | ||
}), | ||
); | ||
|
||
app.on("error", (error) => { | ||
console.error(`Server error: ${error.message}`); | ||
console.error(error.stack); | ||
}); | ||
|
||
// Logging session creation and destruction | ||
app.use((req, res, next) => { | ||
const sess = req.session; | ||
// Make session available to all views | ||
res.locals.session = sess; | ||
if (!sess.views) { | ||
sess.views = 1; | ||
console.log("Session created at: ", new Date().toISOString()); | ||
} else { | ||
sess.views++; | ||
console.log( | ||
`Session accessed again at: ${new Date().toISOString()}, Views: ${sess.views}, User ID: ${sess.userId || '(unauthenticated)'}`, | ||
); | ||
} | ||
next(); | ||
}); | ||
|
||
// Authentication Routes | ||
app.use(authRoutes); | ||
|
||
// API Routes | ||
app.use(apiRoutes); // Use API routes in the application | ||
|
||
// Root path response | ||
app.get("/", (req, res) => { | ||
res.render("index"); | ||
}); | ||
|
||
// If no routes handled the request, it's a 404 | ||
app.use((req, res, next) => { | ||
res.status(404).send("Page not found."); | ||
}); | ||
|
||
// Error handling | ||
app.use((err, req, res, next) => { | ||
console.error(`Unhandled application error: ${err.message}`); | ||
console.error(err.stack); | ||
res.status(500).send("There was an error serving your request."); | ||
}); | ||
|
||
app.listen(port, () => { | ||
console.log(`Server running at http://localhost:${port}`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<%- include('partials/_head.ejs') %> | ||
<body> | ||
<%- include('partials/_header.ejs') %> | ||
<main role="main" class="container mt-4"> | ||
<div class="text-center"> | ||
<h1>GPTOptimizely</h1> | ||
</div> | ||
</main> | ||
</body> | ||
<%- include('partials/_footer.ejs') %> | ||
<script src="/js/main.js"></script> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<%- include('partials/_head.ejs') %> | ||
<body> | ||
<%- include('partials/_header.ejs') %> | ||
<main role="main"> | ||
<div class="container mt-5"> | ||
<h2>Login</h2> | ||
<% if (typeof error !== 'undefined' && error) { %> | ||
<div class="alert alert-danger" role="alert"> | ||
<%= error %> | ||
</div> | ||
<% } %> | ||
<form action="/auth/login" method="POST"> | ||
<div class="mb-3"> | ||
<input type="text" name="username" placeholder="Username" required class="form-control"> | ||
</div> | ||
<div class="mb-3"> | ||
<input type="password" name="password" placeholder="Password" required class="form-control"> | ||
</div> | ||
<div class="mb-3"> | ||
<button type="submit" class="btn btn-primary">Login</button> | ||
Don't have an account? <a href="/auth/register">Register</a> | ||
</div> | ||
</form> | ||
</div> | ||
</main> | ||
</body> | ||
<%- include('partials/_footer.ejs') %> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<footer class="footer fixed-bottom bg-light"> | ||
<div class="container text-center my-2"> | ||
<span>Copyright © <%= 1900 + new Date().getYear() %> GPTOptimizely</span> | ||
</div> | ||
</footer> | ||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+" crossorigin="anonymous"></script> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>GPTOptimizely</title> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> | ||
<link rel="stylesheet" href="/css/style.css"> | ||
</head> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<nav class="navbar navbar-expand-md navbar-dark bg-dark"> | ||
<a class="navbar-brand" href="/">GPTOptimizely</a> | ||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> | ||
<span class="navbar-toggler-icon"></span> | ||
</button> | ||
<div class="collapse navbar-collapse" id="navbarNav"> | ||
<ul class="navbar-nav"> | ||
<li class="nav-item"> | ||
<a class="nav-link" href="/">Home</a> | ||
</li> | ||
<li class="nav-item"> | ||
<% if (session && session.userId) { %> | ||
<a class="nav-link" href="/auth/logout">Logout</a> | ||
<% } else { %> | ||
<a class="nav-link" href="/auth/login">Login</a> | ||
<% } %> | ||
</li> | ||
</ul> | ||
</div> | ||
</nav> |
Oops, something went wrong.