소스 검색

refactor: added mongoose

hover-contact
ntasicc 3 년 전
부모
커밋
4f8e6a406d
11개의 변경된 파일353개의 추가작업 그리고 180개의 파일을 삭제
  1. 33
    0
      models/person.js
  2. 75
    0
      models/user.js
  3. 2
    0
      package.json
  4. 6
    25
      pages/api/auth/[...nextauth].js
  5. 21
    45
      pages/api/auth/signup.js
  6. 51
    34
      pages/api/data.js
  7. 30
    34
      pages/api/single-data/[dataId].js
  8. 39
    29
      pages/api/single-data/index.js
  9. 6
    3
      pages/single-data/[dataId].js
  10. 42
    2
      utils/helpers/dbHelpers.js
  11. 48
    8
      yarn.lock

+ 33
- 0
models/person.js 파일 보기

@@ -0,0 +1,33 @@
const mongoose = require('mongoose');

const PersonSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'Please provide a name.'],
maxlength: [60, 'Name cannot be more than 60 characters'],
trim: true,
},
age: {
type: Number,
required: [true, 'Please provide an age.'],
validate(value) {
if (value < 0) {
throw new Error('Age must be a postive number');
}
},
},
gender: {
type: String,
required: [true, 'Please provide a gender.'],
trim: true,
},
customID: {
type: String,
required: true,
unique: true,
},
});

const Person = mongoose.models.Person || mongoose.model('Person', PersonSchema);

module.exports = Person;

+ 75
- 0
models/user.js 파일 보기

@@ -0,0 +1,75 @@
import {
hashPassword,
verifyPassword,
} from '../utils/helpers/hashPasswordHelpers';

const mongoose = require('mongoose');
const validator = require('validator');

const UserSchema = new mongoose.Schema({
fullName: {
type: String,
required: [true, 'Please provide a name.'],
maxlength: [60, 'Name cannot be more than 60 characters'],
trim: true,
},
username: {
type: String,
required: [true, 'Please provide a name.'],
maxlength: [60, 'Name cannot be more than 60 characters'],
trim: true,
unique: true,
},
email: {
type: String,
unique: true,
required: true,
trim: true,
lowercase: true,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error('Email is invalid');
}
},
},
password: {
type: String,
required: true,
minlength: 7,
trim: true,
validate(value) {
if (value.toLowerCase().includes('password')) {
throw new Error('Password cannot contain "password"');
}
},
},
});

UserSchema.statics.findByCredentials = async (username, password) => {
const user = await User.findOne({ username });

if (!user) {
throw new Error('Unable to login');
}

const isMatch = await verifyPassword(password, user.password);

if (!isMatch) {
throw new Error('Unable to login');
}

return user;
};

UserSchema.pre('save', async function (next) {
const user = this;

if (user.isModified('password')) {
user.password = await hashPassword(user.password);
}

next();
});

const User = mongoose.models.User || mongoose.model('User', UserSchema);
module.exports = User;

+ 2
- 0
package.json 파일 보기

@@ -23,6 +23,7 @@
"date-fns": "^2.29.1",
"formik": "^2.2.9",
"mongodb": "^4.8.1",
"mongoose": "^6.5.2",
"next": "12.2.3",
"next-auth": "^4.10.2",
"next-i18next": "^11.3.0",
@@ -31,6 +32,7 @@
"react-dom": "18.2.0",
"sass": "^1.54.0",
"swr": "^1.3.0",
"validator": "^13.7.0",
"yup": "^0.32.11"
},
"devDependencies": {

+ 6
- 25
pages/api/auth/[...nextauth].js 파일 보기

@@ -1,8 +1,7 @@
import NextAuth from 'next-auth';
import Credentials from 'next-auth/providers/credentials';

import { connectToDatabase } from '../../../utils/helpers/dbHelpers';
import { verifyPassword } from '../../../utils/helpers/hashPasswordHelpers';
import dbConnect from '../../../utils/helpers/dbHelpers';
const User = require('../../../models/user');

export default NextAuth({
session: {
@@ -11,30 +10,12 @@ export default NextAuth({
providers: [
Credentials({
async authorize(credentials) {
const client = await connectToDatabase();

const usersCollection = client.db().collection('users');

const user = await usersCollection.findOne({
username: credentials.username,
});
await dbConnect();

if (!user) {
client.close();
throw new Error('No user found!');
}

const isValid = await verifyPassword(
credentials.password,
user.password
const user = await User.findByCredentials(
credentials.username,
credentials.password
);

if (!isValid) {
client.close();
throw new Error('Could not log you in!');
}

client.close();
return { name: user.fullName };
},
}),

+ 21
- 45
pages/api/auth/signup.js 파일 보기

@@ -1,51 +1,27 @@
import { connectToDatabase } from '../../../utils/helpers/dbHelpers';
import { hashPassword } from '../../../utils/helpers/hashPasswordHelpers';
import User from '../../../models/user';
import dbConnect from '../../../utils/helpers/dbHelpers';

async function handler(req, res) {
if (req.method !== 'POST') {
return;
const { method } = req;

await dbConnect();

switch (method) {
case 'POST': {
try {
const user = await User.create(req.body);
res
.status(201)
.json({ message: `User (${user.fullName}) created sucessfully!` });
} catch (error) {
res.status(400).json({ message: error.message });
}
break;
}
default:
res.status(405).json({ message: 'Method not allowed' });
break;
}

const { fullName, username, email, password } = req.body;

if (
!fullName ||
!username ||
!email ||
!email.includes('@') ||
!password ||
password.trim().length < 7
) {
res.status(422).json({
message: 'Invalid input ',
});
return;
}

const client = await connectToDatabase();
const db = client.db();

const existingUser = await db
.collection('users')
.findOne({ $or: [{ email: email }, { username: username }] });

if (existingUser) {
res.status(422).json({ message: 'User exists already!' });
client.close();
return;
}

const hashedPassword = await hashPassword(password);

const result = await db.collection('users').insertOne({
fullName: fullName,
username: username,
email: email,
password: hashedPassword,
});

res.status(201).json({ message: 'Created user!', result: result });
client.close();
}

export default handler;

+ 51
- 34
pages/api/data.js 파일 보기

@@ -1,9 +1,10 @@
import { connectToDatabase } from '../../utils/helpers/dbHelpers';
const Person = require('../../models/person');
import dbConnect from '../../utils/helpers/dbHelpers';

async function handler(req, res) {
if (req.method !== 'GET') {
return;
}
const { method } = req;
await dbConnect();

const pageIndex = req.query.page;

@@ -14,41 +15,57 @@ async function handler(req, res) {
return;
}

const client = await connectToDatabase();
const db = client.db();
switch (method) {
case 'GET': {
try {
const dataCount = await Person.countDocuments();

const dataCount = await db.collection('randomData').countDocuments();

if ((pageIndex - 1) * 4 >= dataCount) {
res.status(422).json({
message: 'Page does not exist ',
});
client.close();
return;
}
if (dataCount === 0) {
res.status(200).json({
message: 'No data.',
data: [],
dataCount: 0,
});
break;
}

const dataFromDB = await db
.collection('randomData')
.find()
.skip((pageIndex - 1) * 4)
.limit(4)
.toArray();
if ((pageIndex - 1) * 4 >= dataCount) {
throw new Error('Page does not exist!');
}

if (!dataFromDB) {
res.status(422).json({ message: 'No data!' });
client.close();
return;
}
const dataFromDB = await Person.find({})
.skip((pageIndex - 1) * 4)
.limit(4);

res.status(201).json({
message: 'Created user!',
data: dataFromDB,
dataCount: dataCount,
});
if (!dataFromDB) {
throw new Error('No data!');
}

setTimeout(() => {
client.close();
}, 1500);
res.status(200).json({
message: 'Fetched data succesfully',
data: dataFromDB,
dataCount,
});
} catch (error) {
res.status(400).json({ message: error.message });
}
break;
}
case 'POST': {
try {
const person = await Person.create(
req.body
); /* create a new model in the database */
res.status(201).json({ message: 'Created succesfully!', data: person });
} catch (error) {
res.status(400).json({ success: false });
}
break;
}
default:
res.status(405).json({ message: 'Method not allowed' });
break;
}
}

export default handler;

+ 30
- 34
pages/api/single-data/[dataId].js 파일 보기

@@ -1,40 +1,36 @@
import { connectToDatabase } from '../../../utils/helpers/dbHelpers';
const Person = require('../../../models/person');
import dbConnect from '../../../utils/helpers/dbHelpers';

async function handler(req, res) {
if (req.method !== 'GET') {
return;
const { method } = req;

await dbConnect();

switch (method) {
case 'GET': {
try {
const dataId = req.query.dataId;

const person = await Person.findOne({ customID: dataId });

console.log(person);
if (!person) {
throw new Error('Person with this id does not exist!');
}

res.status(200).json({
message: 'Fetch single data successfull!',
singleData: person,
});
} catch (error) {
res.status(400).json({ message: error.message });
}
break;
}
default:
res.status(405).json({ message: 'Method not allowed' });
break;
}

const dataId = req.query.dataId;

let client;

try {
client = await connectToDatabase();
} catch (error) {
res.status(500).json({ message: 'Connecting to the database failed!' });
return;
}

const db = client.db();

const singleData = await db
.collection('randomData')
.findOne({ customID: dataId });

if (!singleData) {
res.status(422).json({ message: 'No data!' });
client.close();
return;
}

res.status(201).json({
message: 'Fetch single data successfull!',
singleData: singleData,
});
setTimeout(() => {
client.close();
}, 1500);
}

export default handler;

+ 39
- 29
pages/api/single-data/index.js 파일 보기

@@ -1,35 +1,45 @@
import { connectToDatabase } from '../../../utils/helpers/dbHelpers';
const Person = require('../../../models/person');
import dbConnect from '../../../utils/helpers/dbHelpers';

async function handler(req, res) {
if (req.method !== 'GET') {
return;
const { method } = req;

await dbConnect();

switch (method) {
case 'GET': {
try {
const dataCount = await Person.countDocuments();

if (dataCount === 0) {
res.status(200).json({
message: 'No data.',
dataIds: [],
});
break;
}

const dataFromDB = await Person.find({}).limit(4);

if (!dataFromDB) {
throw new Error('No data!');
}

const dataIds = dataFromDB.map((item) => item.customID);

res.status(200).json({
message: 'Fetch ids successfull!',
dataIds: dataIds,
});
} catch (error) {
res.status(400).json({ message: error.message });
}
break;
}
default:
res.status(405).json({ message: 'Method not allowed' });
break;
}

const client = await connectToDatabase();
const db = client.db();

const dataFromDB = await db
.collection('randomData')
.find()
.limit(4)
.toArray();

if (!dataFromDB) {
res.status(422).json({ message: 'No data!' });
client.close();
return;
}

const dataIds = dataFromDB.map((item) => item.customID);

res.status(201).json({
message: 'Fetch ids successfull!',
dataIds: dataIds,
});

setTimeout(() => {
client.close();
}, 1500);
}

export default handler;

+ 6
- 3
pages/single-data/[dataId].js 파일 보기

@@ -2,14 +2,15 @@ import DataDetailsCard from '../../components/cards/data-details-card/DataDetail
import { getDataIds } from '../../requests/dataIdsRequest';
import { getSingleData } from '../../requests/singleDataRequest';

function SignelDataPage(props) {
const SignelDataPage = (props) => {
const data = props.selectedData;

console.log(data);
if (!data) {
return <h1>No data!</h1>;
return <h1>{props.message}</h1>;
}
return <DataDetailsCard data={data.singleData} />;
}
};

export async function getStaticProps(context) {
const dataId = context.params.dataId;
@@ -26,6 +27,7 @@ export async function getStaticProps(context) {
return {
props: {
selectedData: null,
message: error.message,
},
revalidate: 60,
};
@@ -40,6 +42,7 @@ export async function getStaticPaths() {
params: { dataId: id },
}));

console.log(paths);
return {
paths: paths,
fallback: 'blocking',

+ 42
- 2
utils/helpers/dbHelpers.js 파일 보기

@@ -1,7 +1,47 @@
import { MongoClient } from "mongodb";
import { MongoClient } from 'mongodb';
import mongoose from 'mongoose';

export async function connectToDatabase() {
const client = await MongoClient.connect(process.env.MONGODB_AUTH);
const client = await MongoClient.connect(process.env.MONGODB_URI);

return client;
}

const MONGODB_URI = process.env.MONGODB_URI;

if (!MONGODB_URI) {
throw new Error(
'Please define the MONGODB_URI environment variable inside .env.local'
);
}

/**
* Global is used here to maintain a cached connection across hot reloads
* in development. This prevents connections growing exponentially
* during API Route usage.
*/
let cached = global.mongoose;

if (!cached) {
cached = global.mongoose = { conn: null, promise: null };
}

async function dbConnect() {
if (cached.conn) {
return cached.conn;
}

if (!cached.promise) {
const opts = {
bufferCommands: false,
};

cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => {
return mongoose;
});
}
cached.conn = await cached.promise;
return cached.conn;
}

export default dbConnect;

+ 48
- 8
yarn.lock 파일 보기

@@ -4785,6 +4785,13 @@ [email protected], debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
dependencies:
ms "2.0.0"

[email protected], debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"

debug@^3.0.0, debug@^3.2.7:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
@@ -4792,13 +4799,6 @@ debug@^3.0.0, debug@^3.2.7:
dependencies:
ms "^2.1.1"

debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"

decamelize-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
@@ -7275,6 +7275,11 @@ junk@^3.1.0:
resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==

[email protected]:
version "2.4.1"
resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.4.1.tgz#7d81ec518204a48c1cb16554af126806c3cd82b0"
integrity sha512-aJ9opVoXroQUPfovYP5kaj2lM7Jn02Gw13bL0lg9v0V7SaUc0qavPs0Eue7d2DcC3NjqI6QAUElXNsuZSeM+EA==

kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -7842,7 +7847,7 @@ mongodb-connection-string-url@^2.5.2:
"@types/whatwg-url" "^8.2.1"
whatwg-url "^11.0.0"

mongodb@^4.8.1:
[email protected], mongodb@^4.8.1:
version "4.8.1"
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.8.1.tgz#596de88ff4519128266d9254dbe5b781c4005796"
integrity sha512-/NyiM3Ox9AwP5zrfT9TXjRKDJbXlLaUDQ9Rg//2lbg8D2A8GXV0VidYYnA/gfdK6uwbnL4FnAflH7FbGw3TS7w==
@@ -7854,6 +7859,31 @@ mongodb@^4.8.1:
optionalDependencies:
saslprep "^1.0.3"

mongoose@^6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-6.5.2.tgz#630ae67c4d2576635ba1f859b2840560b27b7775"
integrity sha512-3CFDrSLtK2qjM1pZeZpLTUyqPRkc11Iuh74ZrwS4IwEJ3K2PqGnmyPLw7ex4Kzu37ujIMp3MAuiBlUjfrcb6hw==
dependencies:
bson "^4.6.5"
kareem "2.4.1"
mongodb "4.8.1"
mpath "0.9.0"
mquery "4.0.3"
ms "2.1.3"
sift "16.0.0"

[email protected]:
version "0.9.0"
resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.9.0.tgz#0c122fe107846e31fc58c75b09c35514b3871904"
integrity sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==

[email protected]:
version "4.0.3"
resolved "https://registry.yarnpkg.com/mquery/-/mquery-4.0.3.tgz#4d15f938e6247d773a942c912d9748bd1965f89d"
integrity sha512-J5heI+P08I6VJ2Ky3+33IpCdAvlYGTSUjwTPxkAr8i8EoduPMBX2OY/wa3IKZIQl7MU4SbFk8ndgSKyB/cl1zA==
dependencies:
debug "4.x"

[email protected]:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -9693,6 +9723,11 @@ side-channel@^1.0.4:
get-intrinsic "^1.0.2"
object-inspect "^1.9.0"

[email protected]:
version "16.0.0"
resolved "https://registry.yarnpkg.com/sift/-/sift-16.0.0.tgz#447991577db61f1a8fab727a8a98a6db57a23eb8"
integrity sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ==

signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
@@ -10706,6 +10741,11 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"

validator@^13.7.0:
version "13.7.0"
resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857"
integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==

vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"

Loading…
취소
저장