I'm facing a n error when throwing a BadRequestException which is not supposed to happen - asynchronous

I am writing a basic signup api and using find() function to check if there are any duplicate api and in an if() condition im throwing a BadRequestException but it is giving me an error if the input email is already in use. A very similar code in another project is not giving any error but this is.
This is the code snippet. when given an email id already registered in the database it is supposed to throw an exception.
import { Injectable, BadRequestException } from '#nestjs/common';
import { UsersService } from './users.service';
import { randomBytes, scrypt as _scrypt } from 'crypto';
import { promisify } from 'util';
const scrypt = promisify(_scrypt);
#Injectable()
export class AuthService {
constructor(private usersService: UsersService) {}
async signup(ogname: string,
email: string,
password: string,
phone: string,
date_of_birth: Date,
type: string,) {
// See if email is in use
const name = null;
const users = await this.usersService.find(name, email);
console.log(users.length);
if (users.length) {
throw new BadRequestException('email in use');
}
// Hash the users password
// Generate a salt
const salt = randomBytes(8).toString('hex');
// Hash the salt and the password together
const hash = (await scrypt(password, salt, 32)) as Buffer;
// Join the hashed result and the salt together
const result = salt + '.' + hash.toString('hex');
//Create a new user and save it
const user = await this.usersService.create(ogname, email, result, phone, date_of_birth, type)
// return the user
return user;
}
signin() {}
}
expected result:
{
"statusCode": 400,
"message": "email in use",
"error": "Bad Request"
}
Unexpected result:
here is the github link for the entire code:
https://github.com/chaitanya2108/appaya_basketball_club

I've just read the code you posted on GitHub, it's quite different than the code you posted here, then I cannot reproduce the issue.
However, I can give you some suggestion for better implementations:
Try the Unique decorator: https://typeorm.io/decorator-reference#column
Use try-catch in asynchronous in order to handle error when signing up.

Related

How to implement iron-session with session id

I am using iron-session, next-connect with nextjs in our webapp and one of the requirements is to publish analytics events from our frontend code, like page views, button clicks and other custom events. These events are stored in our database and used by our data analyst with PowerBI.
Our webapp takes a user on an onboarding journey, then once it's done, we create an account for the user and redirects to dashboard. For the onboarding part, we don't have a user id yet while in the dashboard, we already do. However, we want to be able to track the user journey in the webapp so we need an identifier that is persisted throughout the whole journey. Thus, we think of a session id with the iron-session.
Now iron-session doesn't have a concept of session id, so I am trying to implement it myself. The session id will be our identifier of the user in our events table.
Here is the withSession middleware used with next-connect
import { getIronSession } from "iron-session";
import type { IncomingMessage } from "http";
import type { NextApiRequest } from "next";
import { nanoid } from "nanoid";
import appConfig from "#/backend/app.config";
export const sessionOptions = {
password: appConfig.secret,
cookieName: appConfig.cookies.sessionToken.name,
cookieOptions: appConfig.cookies.sessionToken.options,
};
export async function withSession(
req: IncomingMessage | NextApiRequest,
res: any,
next: any
) {
const session = await getIronSession(req, res, sessionOptions);
if (!session.id) session.id = nanoid(32);
req.session = session;
await req.session.save();
return next();
}
declare module "iron-session" {
interface IronSessionData {
user?: { id: string };
id: string;
}
}
And a route that will use the middleware
const router = createRouter<NextApiRequest, NextApiResponse>()
.use(...([withSession, withLogger, withTenant] as const))
.get(async (req, res) => {
// Authenticate user
req.session.user = { id: userId };
await req.session.save();
return res.redirect("/");
});
export default router.handler();
Is this a correct implementation of the said requirement?
Some libraries implement a kind of session.regenerate() when a user perform signIn and signOut. Do I need to implement it too? If I do, I will lose the identifier that persists throughout the whole user journey.
since you are using typescript first define the type of session object
declare module "iron-session" {
interface IronSessionData {
nameOfSessionObject?: {
// in your implementation you were creating req.user and req.id
// you could overwrite the req properties
user?: { id: string };
// you can manually create on the server
id: string;
};
}
}
create a wrapper session function
export function withSession(handler: any) {
return withIronSessionApiRoute(handler, {
password: appConfig.secret,
cookieName: appConfig.cookies.sessionToken.name,
// Said in another way, the browser will not send a cookie with the secure attribute set over an unencrypted HTTP request
cookieOptions: appConfig.cookies.sessionToken.options,
})}
create the session object. you do not use getIronSession when creating a session.
you need that when you need to access to the session object in middleware
export default withSessio(
async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === "GET") {
try {
const sessionObj={....}
req.session.nameOfSessionObject={...sessionObj}
await req.session.save();
// whatever you want to return
return res.json(sessionObj);
} catch (error) {
console.error("error in verify post req", error);
// 422 Unprocessable Entity
res.status(422).send({ message: "Cannot create SESSION" });
}
} else if (req.method === "POST") {
try {
..HANDLE POST HERE
} catch (error) {
res.status(422).send({ message: "Cannot generate a SESSION" });
}
} else {
return res.status(200).json({ message: "Invalid api Route" });
}
}
);
now you can import above handler and connect with next-connect

Unexpected firebase.auth().currentUser.uid in a web app

I have this line of code in a web app (on Firebase):
registerWithEmailAndPassword(name, email, password);
An email, password and a name are provided, and a new user account is created when the code is executed.
All this seems normal, but what is less expected (at least to me) is that shortly after I find myself having the UID of the newly created user as my firebase.auth().currentUser.uid.
I do not do anything to log in as this new user.
So I wonder what is happening under the hood.
Any idea or explanation would be helpful.
registerWithEmailAndPassword is not a built in Firebase SDK method according to the API Reference. However, based on the name of that method, it is probably implemented in a way that makes use of createUserWithEmailAndPassword (modern / legacy) and updateProfile (modern / legacy) under the hood.
Importantly, createUserWithEmailAndPassword both creates the new user AND signs them in immediately. Because a user has been signed in, any onAuthStateChanged (modern / legacy) listeners will fire and the Auth instance's currentUser (modern / legacy) property will return the user's details.
This registerWithEmailAndPassword function probably looks like:
// Modern Firebase Syntax
import { getAuth, createUserWithEmailAndPassword, updateProfile } from "firebase/auth";
export const registerWithEmailAndPassword = async (displayName: string, email: string, password: string) => {
// gets default FirebaseAuth
const auth = getAuth();
// creates and signs in a new user with the given email and password, and grabs the new user's details
const { user } = await createUserWithEmailAndPassword(auth, email, password);
// update the user's details with their name
await updateProfile(user, { displayName });
}
// Legacy Firebase Syntax
import * as firebase from "firebase";
import "firebase/auth";
export const registerWithEmailAndPassword = async (displayName: string, email: string, password: string) => {
// gets default FirebaseAuth
const auth = firebase.auth();
// creates and signs in a new user with the given email and password, and grabs the new user's details
const { user } = await auth.createUserWithEmailAndPassword(email, password);
// update the user's details with their name
await user.updateProfile({ displayName });
}
To adapt this code so that you can sign up another user instead of yourself, you need to initialize a second Firebase app in the background. As this second app will have its own authentication state, you can use it to create/update other users without affecting the user signed into the default app.
// Modern Firebase Syntax
import { getApp, getApps, initializeApp } from "firebase/app";
import { getAuth, createUserWithEmailAndPassword, updateProfile, signOut } from "firebase/auth";
// creates/reuses a secondary app as needed, based off the default app's configuration
// consider moving this to your 'firebase.ts' file
const getSecondaryApp = () => {
return getApps().find(a => a.name === 'secondary')
|| initializeApp(getApp().options, 'secondary'); // .options is a copy of the object passed into the default app's initializeApp()
}
export const registerWithEmailAndPassword = async (displayName: string, email: string, password: string) => {
// gets secondary FirebaseAuth
const secondaryAuth = getAuth(getSecondaryApp());
// creates and signs in a new user with the given email and password, and grabs the new user's details
const { user } = await createUserWithEmailAndPassword(secondaryAuth, email, password);
// update the user's details with their name
await updateProfile(user, { displayName });
// sign out the newly created user
await signOut(secondaryAuth);
// return the new user's info to the caller
return user; // depending on use, consider returning user.toJSON()
}
// Legacy Firebase Syntax
import * as firebase from "firebase";
import "firebase/auth";
// creates/reuses a secondary app as needed, based off the default app, based off the default app's configuration
// consider moving this to your 'firebase.ts' file
const getSecondaryApp = () => {
return firebase.apps.find(a => a.name === 'secondary')
|| firebase.initializeApp(firebase.app().options, 'secondary'); // .options is a copy of the object passed into the default app's initializeApp()
}
export const registerWithEmailAndPassword = async (displayName: string, email: string, password: string) => {
// gets secondary FirebaseAuth
const secondaryAuth = firebase.auth(getSecondaryApp());
// creates and signs in a new user with the given email and password, and grabs the new user's details
const { user } = await secondaryAuth.createUserWithEmailAndPassword(email, password);
// update the user's details with their name
await user.updateProfile({ displayName });
// sign out the newly created user
await secondaryAuth.signOut();
// return the new user's info to the caller
return user; // depending on use, consider returning user.toJSON()
}

Unable to fetch an already created account

I have the following api method, which I am calling when a button is clicked in the front end:-
export const sendMessage = async (content, roomPublicKey) => {
const { wallet, program, provider } = useWorkspace()
const message = web3.Keypair.generate()
const tx = await program.value.rpc.sendMessage(content, roomPublicKey, {
accounts: {
message: message.publicKey,
author: wallet.value.publicKey,
systemProgram: web3.SystemProgram.programId,
},
signers: [message]
})
console.log(tx);
const messageAccount = await program.value.account.message.fetch(message.publicKey)
}
sendMessage rpc call is creating a new account, and I am then trying to fetch the just created account. But I am getting an error that no such account exists.
I logged the transaction hash and checked on solana explorer and it seems that the account is definitely there, but I am not sure why I am not able to fetch that account
I would recommend always confirming the transactions you run on your code, because the problem may be that you are creating the account, but you check it too fast and the RCP has not been updated yet or something.
That is considering you did everything correctly in your contract code, but i can't know that since you didn't provide it.
Add this line of code after your transaction request:
await program.provider.connection.confirmTransaction(tx);
so it will look like this:
export const sendMessage = async (content, roomPublicKey) => {
const { wallet, program, provider } = useWorkspace()
const message = web3.Keypair.generate()
const tx = await program.value.rpc.sendMessage(content, roomPublicKey, {
accounts: {
message: message.publicKey,
author: wallet.value.publicKey,
systemProgram: web3.SystemProgram.programId,
},
signers: [message]
})
console.log(tx);
await program.provider.connection.confirmTransaction(tx);
const messageAccount = await program.value.account.message.fetch(message.publicKey)
}
Also another check you can do is getting the account info to see if it was created correctly, since fetch uses the discriminator from anchor to determine if the account is the right type.
like this :
const collectionPDAAccount = await program.provider.connection.getAccountInfo(message.publicKey);
Hope this helps!

res.redirect in API route NextJS gives a loop

I have this code in my /api/[verificationToken] which is when accessed by the user, the verification token will be updated. For now, I am trying to check if the token exists in the database and corresponds to a registered email.
import prisma from "../../../lib/prisma";
export default async function handler(req, res) {
const token = req.query;
const findEmail = await prisma.user.findFirst({
where: {
token: token.verificationToken,
},
});
if (findEmail) {
console.log("email exists");
} else {
console.log("email doesn't exist");
return res.redirect("/auth/login");
}
}
The problem is, when I go to http://localhost:3000/auth/api/nonexistenttoken, "email doesn't exist" displays in a loop. I have also tried
res.writeHead(302, {
Location: '/auth/login'
});
res.end();
But it still gives me the same loop. What I want to happen is that when the token doesn't exist (which also means the email also doesn't), it should redirect the user to the login page.

React native firebase - facebook sign-in

Im following the official code sample provided by RNFB....code below
Problem is that you dont get past the line const facebookCredential = firebase.FacebookAuthProvider.credential(data.accessToken);.....it appears that the firebase.FacebookAuthProvider method is showing as undefined so you dont get the facebookCredential variable back
import { firebase } from '#react-native-firebase/auth';
async function onFacebookButtonPress() {
// Attempt login with permissions
const result = await LoginManager.logInWithPermissions(['public_profile', 'email']);
if (result.isCancelled) {
throw 'User cancelled the login process';
}
// Once signed in, get the users AccesToken
const data = await AccessToken.getCurrentAccessToken();
if (!data) {
throw 'Something went wrong obtaining access token';
}
// Create a Firebase credential with the AccessToken
const facebookCredential = auth.FacebookAuthProvider.credential(data.accessToken);
// Sign-in the user with the credential
return auth().signInWithCredential(facebookCredential);
}
The example linked seems to be missing the declaration of an auth variable. We need to get it from the imported firebase moduled.
Instead of:
auth.FacebookAuthProvider
We should be using:
firebase.auth.FacebookAuthProvider

Resources