Skip to content

Commit

Permalink
Added sidebar, protected route, persisted state in frontend and authe…
Browse files Browse the repository at this point in the history
…ntication and database models in backend
  • Loading branch information
winarmarco committed Feb 26, 2023
1 parent 0165ddd commit dd2fe80
Show file tree
Hide file tree
Showing 25 changed files with 4,762 additions and 592 deletions.
14 changes: 14 additions & 0 deletions back-end/model/ChatSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const mongoose = require("mongoose");

const chatSchema = new mongoose.Schema({
messages: [
{
message: {type: String},
sentBy: {type: String, required: true, enum: ["bot", "user"]},
},
],
});

const Chat = mongoose.model('Chat', chatSchema);

module.exports = Chat
38 changes: 38 additions & 0 deletions back-end/model/UserSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const mongoose = require("mongoose");
const bcrypt = require("bcrypt");

const userSchema = new mongoose.Schema({
email: {type: String, required: true, unique: true},
username: {type: String, required: true, unique: true},
password: {type: String, required: true},
chats: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Chat',
}]
});

userSchema.pre("save", function (next) {
const user = this;
bcrypt.hash(user.password, 10, (err, hashedPassword) => {
if (err) {
return next(err);
}

user.password = hashedPassword;
next();
});
});

userSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, (err, isMatch) => {
if (err) {
cb(err);
}

cb(null, isMatch);
})
}

const User = mongoose.model('User', userSchema);

module.exports = User;
4,592 changes: 4,120 additions & 472 deletions back-end/package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion back-end/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
"license": "ISC",
"dependencies": {
"axios": "^1.3.2",
"bcrypt": "^5.1.0",
"body-parser": "^1.20.1",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2"
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"mongoose": "^6.9.2"
}
}
50 changes: 50 additions & 0 deletions back-end/routes/authentication.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const express = require("express");
const User = require("../model/UserSchema");
const { createJSONToken } = require("../util/auth");
const router = express.Router();

router.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = await User.findOne({ username });
if (!user) {
return res.status(401).json({ message: 'Invalid credentials' });
}
user.comparePassword(password, (err, isMatch) => {
if (err) {
return res.status(401).json({ message: 'Invalid credentials' });
}
if (!isMatch) {
return res.status(401).json({ message: 'Invalid credentials' });
}

const userID = user._id;
const token = createJSONToken({userID});

res.status(200).json({
token: token,
})
});
});

router.post('/signup', async (req, res) => {
const {email, username, password, confirmPassword} = req.body;


try {
const user = new User({
username,
email,
password,
chats: [],
})

console.log(user);
await user.save();

res.status(201).json({message: 'User created'});
} catch (err) {
res.status(401).json({message: err.message});
}
})

module.exports = router;
8 changes: 8 additions & 0 deletions back-end/routes/message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const express = require("express");
const User = require("../model/UserSchema");
const router = express.Router();

router.post('/', (req, res) => {


})
19 changes: 13 additions & 6 deletions back-end/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,33 @@ const express = require("express");
const axios = require("axios");
const cors = require("cors");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");

const authRouter = require("./routes/authentication");

mongoose.set('strictQuery', true);
mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true });
const app = express();

var corsOptions = {
const corsOptions = {
origin: 'http://localhost:3000',
optionsSuccessStatus: 200
}

app.use(cors(corsOptions));

// app.use((req, res, next) => {
// res.setHeader('Access-Control-Allow-Origin', '*');
// res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PATCH,DELETE');
// res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');
// next();
// });

app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());

app.post("/", async (req, res) => {
console.log(req.body);
res.send(req.body);
});
app.use('/', authRouter);

app.post("/text-completions", async (req, res) => {
const prompt = req.body.prompt;
Expand Down
14 changes: 14 additions & 0 deletions back-end/util/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const { sign, verify } = require("jsonwebtoken");

const KEY = process.env.SECRET_KEY;

function createJSONToken(userID) {
return sign({userID}, KEY, {expiresIn: '1h'});
}

function validateJSONToken(token) {
return verify(token, secret);
}

exports.createJSONToken = createJSONToken;
exports.validateJSONTOken = validateJSONToken;
34 changes: 34 additions & 0 deletions front-end/package-lock.json

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

3 changes: 3 additions & 0 deletions front-end/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"react-router-dom": "^6.8.1",
"react-scripts": "5.0.1",
"react-textarea-autosize": "^8.4.0",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.4.2",
"tailwind-scrollbar": "^2.1.0",
"uuidv4": "^6.2.13",
"web-vitals": "^2.1.4"
},
Expand Down
47 changes: 27 additions & 20 deletions front-end/src/App.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
import {createBrowserRouter, RouterProvider} from "react-router-dom";
import AuthPage from "./pages/AuthPage";
import AuthPage, {action as authAction} from "./pages/AuthPage";
import Private from "./util/Private";
import ChatPage from "./pages/ChatPage";

const router = createBrowserRouter([
{
path: "/",
element: <ChatPage />,
// errorElement: <ErrorPage />,
children: [],
},
{
path: "/login",
element: <AuthPage mode="login"/>,
},
{
path: "/signup",
element: <AuthPage mode="signup"/>,
},
{
path: "/chat/:chatId",
element: <ChatPage />,
},
{
path: "/",
element: <ChatPage />,
// errorElement: <ErrorPage />,
children: [],
},
{
path: "/login",
action: authAction,
element: <AuthPage mode="login" />,
},
{
path: "/signup",
action: authAction,
element: <AuthPage mode="signup" />,
},
{
path: "/chat/:chatId",
element: (
<Private>
<ChatPage />
</Private>
),
},
]);

function App() {
return <RouterProvider router={router} />;
return <RouterProvider router={router} />;
}

export default App;
Loading

0 comments on commit dd2fe80

Please sign in to comment.