I'm trying to pull data from a document containing a logged-in user from the MongoDB database. However, req. the query doesn't seem to pass.
case "GET": {
const { userName } = req.query;
const users = await db
.collection("USERS")
.find({ user: { $in: [userName] } })
.toArray();
res.json(users);
break;
}
export async function getStaticProps() {
const res = await fetch(`http://localhost:3000/api/usersAPI`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
let users = await res.json();
return {
props: { users },
};
}
Related
The following works fine, but I have noticed that it is really slow login in a client. How can I make it faster?
import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
import { ObjectId } from 'mongodb'
import { MongoDBAdapter } from "#next-auth/mongodb-adapter"
import clientPromise from "../../../lib/mongodb";
import { v4 as uuidv4 } from 'uuid';
var CryptoJS = require("crypto-js");
const sFinder = async (task, token) => {
try{
const client = await clientPromise;
const database = client.db('DRN1');
const ses = await database.collection('sessions');
switch (task) {
case 1:
const result = await ses.find({
"userId": ObjectId(token.uuid)
}).sort({"_id":-1}).limit(1).toArray();
if (!result) {
return 202;
}
else{
return result[0].sessionToken
}
break;
case 2:
const insertResult = await ses.insertOne({"userId":token.uuid, "sessionToken":token.accessToken});
if (!insertResult) {
return 203;
}
else{
return insertResult
}
break;
case 3:
var expdate = new Date(token.exp * 1000);
const UpdateResult = await ses.updateOne({"userId":ObjectId(token.uuid), "sessionToken":token.accessToken},
{ $set: {"expires": expdate}}, { upsert: true });
if (!UpdateResult) {
return 203;
}
else{
return UpdateResult
}
break;
default:
break;
}
} catch(e){
console.error(e);
}
}
export default NextAuth({
adapter: MongoDBAdapter(clientPromise),
session: {
strategy: 'jwt',
jwt: true,
},
providers: [
CredentialsProvider({
name: 'DRN1',
credentials: {
username: { label: "Username", type: "text"},
password: { label: "Password", type: "password" }
},
async authorize(credentials, req) {
try{
const client = await clientPromise;
const database = client.db('DRN1');
const users = await database.collection('users');
const result = await users.findOne({
username: credentials.username,
});
if (!result) {
throw new Error('No user found with the username');
}
var bytes = CryptoJS.AES.decrypt(result.password, process.env.PASS_ENC);
var decryptedData = bytes.toString(CryptoJS.enc.Utf8);
//Check hased password with DB password
if(decryptedData != credentials.password){
throw new Error('Password doesnt match');
}
return {uuid:result._id, username: result.username, email: result.email, type:result.type, "sessionID":uuidv4()};
} catch(e){
console.error(e)
}
}
})
],
callbacks: {
signIn: async ({ user, account, profile, email, credentials }) => {
account.accessToken = user.sessionID
account.uuid = user.uuid
const test = await sFinder(2,account)
return true
},
jwt: async ({ token, account }) => {
if (account) {
token.uuid = account.uuid
token.accessToken = account.accessToken
}
const lastUsedToken = await sFinder(1,token)
const updateTokenExpire = await sFinder(3,token)
if(lastUsedToken != token.accessToken){
// console.log("I have made it an error")
token.error = 555;
}
return token
},
session: async ({ session, token, user }) => {
session.uuid = token.uuid
if(!token.accessToken){
//OAUTH Accounts
session.accessToken = uuidv4()
}else{
session.accessToken = token.accessToken
}
if(token.error == 555){
session.error = 555
}
return session
}
},
pages:{
error: 'signin'
},
theme: {
colorScheme: "dark", // "auto" | "dark" | "light"
brandColor: "", // Hex color code
logo: "https://storage.googleapis.com/radiomedia-images/station_logos/v2/DRN1_small.png" // Absolute URL to image
}
});
I believe what is slowing it down is the following
callbacks: {
signIn: async ({ user, account, profile, email, credentials }) => {
account.accessToken = user.sessionID
account.uuid = user.uuid
const test = await sFinder(2,account)
return true
},
jwt: async ({ token, account }) => {
if (account) {
token.uuid = account.uuid
token.accessToken = account.accessToken
}
const lastUsedToken = await sFinder(1,token)
const updateTokenExpire = await sFinder(3,token)
if(lastUsedToken != token.accessToken){
// console.log("I have made it an error")
token.error = 555;
}
return token
},
session: async ({ session, token, user }) => {
session.uuid = token.uuid
if(!token.accessToken){
//OAUTH Accounts
session.accessToken = uuidv4()
}else{
session.accessToken = token.accessToken
}
if(token.error == 555){
session.error = 555
}
return session
}
},
Mainly all the awaits, but the await functions are to make sure the user is not login on another device. As we log the old devices out automatically.
I'm working on a project with Next.js and Prisma. In one of my API routes, I have a three queries. The results of the first and second queries are used in the third query. I'd like to do all three operations as a transaction and then return the data from the first query in the response.
I'm familiar with using prisma.$transaction but I don't know how to write it in this case where results #1 and #2 are used by query #3. Here are the queries as they are written now. Thanks in advance!
const { boardId } = req.body
const { description, status, title } = req.body.task
const createTask = await prisma.task.create({
data: {
board: boardId,
description,
status,
title
}
})
const statusArray = await prisma.board.findUnique({
where: {
id: boardId
},
select: {
[status]: true
}
})
const updateBoardStatusArray = await prisma.board.update({
where: {
id: boardId
},
data: {
[status]: {
set: [...statusArray[status], createTask.id]
}
}
})
// return data from first query
res.status(201).json({task: createTask})
Here you go:
const { boardId } = req.body;
const { description, status, title } = req.body.task;
const [createTask] = await prisma.$transaction(async (prisma) => {
const createTask = await prisma.task.create({
data: {
board: boardId,
description,
status,
title,
},
});
const statusArray = await prisma.board.findUnique({
where: {
id: boardId,
},
select: {
[status]: true,
},
});
const updateBoardStatusArray = await prisma.board.update({
where: {
id: boardId,
},
data: {
[status]: {
set: [...statusArray[status], createTask.id],
},
},
});
return [createTask, statusArray, updateBoardStatusArray];
});
// return data from first query
res.status(201).json({ task: createTask });
You can learn more about Interactive Transaction here
I am trying to decrease the quantity of something by 1 in both mongodb and website together. I have already used an update option to change the quantity. Now I need to only decrease it by 1.
const handleRestockItems = (event) => {
event.preventDefault();
const quantity = event.target.quantity.value;
const RestockItem = { quantity };
// send data to the server
const url = `http://localhost:5000/item/${itemId}`;
fetch(url, {
method: "PUT",
headers: {
"content-type": "application/json",
},
body: JSON.stringify(RestockItem),
})
.then((res) => res.json())
.then((data) => {
console.log("success", data);
alert("Restock Items successfully!!!");
event.target.reset();
// Adding reload button to show updated items on UI
window.location.reload(false);
});
};
MongoDB code:
app.put("/item/:id", async (req, res) => {
const id = req.params.id;
const updatedUser = req.body;
const filter = { _id: ObjectId(id) };
const options = { upsert: true };
const updatedDoc = {
$set: {
quantity: updatedUser.quantity,
},
};
const result = await iCollection.updateOne(filter, updatedDoc, options);
res.send(result);
});
I have a problem with my authentication via Coinbase (using Nextauth) on NextJS app.
I made this code below, and it saves the profile well in my Mongodb database. But when I re-login, accesstoken and refreshtoken are not changed...
So I can’t use the APIs afterwards.
import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';
async function refreshAccessToken(token) {
try {
const url =
"https://api.coinbase.com/oauth/token?" +
new URLSearchParams({
client_id: process.env.COINBASE_CLIENT_ID,
client_secret: process.env.COINBASE_SECRET_ID,
grant_type: "refresh_token",
refresh_token: token.refreshToken,
})
const response = await fetch(url, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
method: "POST",
})
const refreshedTokens = await response.json()
if (!response.ok) {
throw refreshedTokens
}
return {
...token,
accessToken: refreshedTokens.access_token,
accessTokenExpires: Date.now() + refreshedTokens.expires_in * 1000,
refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, // Fall back to old refresh token
}
} catch (error) {
console.log(error)
return {
...token,
error: "RefreshAccessTokenError",
}
}
}
export default NextAuth({
// Configure one or more authentication providers
providers: [
Providers.Coinbase({
clientId: process.env.COINBASE_CLIENT_ID,
clientSecret: process.env.COINBASE_SECRET_ID,
callbackUrl: process.env.COINBASE_CALLBACKURL,
scope: "wallet:accounts:read",
}),
],
callbacks: {
async jwt({ token, user, account, profile, isNewUser }) {
// Initial sign in
if (account && user) {
return {
accessToken: user.data.access_token,
accessTokenExpires: Date.now() + user.data.expires_in * 1000,
refreshToken: user.data.refresh_token,
user,
}
}
// Return previous token if the access token has not expired yet
if (Date.now() < token.accessTokenExpires) {
return token
}
// Access token has expired, try to update it
return refreshAccessToken(token)
},
async session(session, token) {
session.accessToken = token.accessToken
return session
}
},
events: {
async signIn(message) { console.log('success signin') },
async signOut(message) { console.log('success signout') },
async createUser(message) { console.log('success user create') },
async updateUser(message) { console.log('success update user') },
async session(message) { console.log('success session') },
async error(message) { console.log('error') }
},
// A database is optional, but required to persist accounts in a database
database: `mongodb+srv://${process.env.NOSQL_USER}:${process.env.NOSQL_PWD}#${process.env.NOSQL_HOST}/${process.env.NOSQL_TABLE}`,
});
I’m still a beginner on NextJS and React in particular:) Thanks for your help
I want to store token and user information in local storage ,things like store token and userId are okay except I can't include users detail information like email
this.login = function (data) {
var loginResults = Restangular.one('/users/login')
.post(undefined, data)
.then(function (data) {
var mytoken = data.id;
storeToken(data);
Restangular.setDefaultHeaders({ accept: 'application/json', access_token: mytoken });
},
function (Response) {
console.log("There was an error.");
});
return loginResults;
}
Finally I got the correct answer to include "user" here is the result....
this.login = function (data) {
var loginResults = Restangular.one('/persons/login')
.post(undefined, data, {
include: "user"
})
.then(function (data) {
var mytoken = data.id;
storeToken(data);
Restangular.setDefaultHeaders({ accept: 'application/json', access_token: mytoken });
$state.go('home');
}, function (Response) {
console.log("There was an error.");
alert("Login Failed");
});
return loginResults;
}