custom session next js next-auth - javascript

I got an problem when migrate my js file jo tsx, what I'm doing is signin with credentials and custom the session user to my user data
// api/auth/[...nextauth].js
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
import { ConnectDatabase } from "../../../lib/db";
import { VertifyPassword } from "../../../lib/password";
import { getSelectedUser } from "../../../helpers/database";
import { MongoClient } from "mongodb";
import { NextApiRequest } from "next";
interface credentialsData {
data: string | number;
password: string;
}
export default NextAuth({
session: {
jwt: true,
},
callbacks: {
async session(session) {
const data = await getSelectedUser(session.user.email);
session.user = data.userData;
// inside data.userdata is a object
// {
// _id: '60a92f328dc04f58207388d1',
// email: 'user#user.com',
// phone: '087864810221',
// point: 0,
// role: 'user',
// accountstatus: 'false'
// }
return Promise.resolve(session);
},
},
providers: [
Providers.Credentials({
async authorize(credentials: credentialsData, req: NextApiRequest) {
let client;
try {
client = await ConnectDatabase();
} catch (error) {
throw new Error("Failed connet to database.");
}
const checkEmail = await client
.db()
.collection("users")
.findOne({ email: credentials.data });
const checkPhone = await client
.db()
.collection("users")
.findOne({ phone: credentials.data });
let validData = {
password: "",
email: "",
};
if (!checkEmail && !checkPhone) {
client.close();
throw new Error("Email atau No HP tidak terdaftar.");
} else if (checkEmail) {
validData = checkEmail;
} else if (checkPhone) {
validData = checkPhone;
}
const checkPassword = await VertifyPassword(
credentials.password,
validData.password
);
if (!checkPassword) {
client.close();
throw new Error("Password Salah.");
}
client.close();
// inside validData is a object
// {
// _id: '60a92f328dc04f58207388d1',
// email: 'user#user.com',
// phone: '087864810221',
// point: 0,
// role: 'user',
// accountstatus: 'false'
// }
return validData;
},
}),
],
});
// as default provider just return session.user just return email,name, and image, but I want custom the session.user to user data what I got from dababase
This in client side
// index.tsx
export const getServerSideProps: GetServerSideProps<{
session: Session | null;
}> = async (context) => {
const session = await getSession({ req: context.req });
if (session) {
if (session.user?.role === "admin") {
return {
redirect: {
destination: "/admin/home",
permanent: false,
},
};
}
}
return {
props: {
session,
},
};
};
But in client side I got warning
Property 'role' does not exist on type '{ name?: string; email?: string; image?: string;
actually my file still working fine, but when my file in js format, its not warning like that
can someone help me to fix it ?

Not sure if you found a workaround yet but you need to configure the jwt callback as well! Here is an example from a project of mine:
callbacks: {
async session(session, token) {
session.accessToken = token.accessToken;
session.user = token.user;
return session;
},
async jwt(token, user, account, profile, isNewUser) {
if (user) {
token.accessToken = user._id;
token.user = user;
}
return token;
},
},
To explain things. jwt function always runs before session, so whatever data you pass to jwt token will be available on session function and you can do whatever you want with it. In jwt function i check if there is a user because this only returns data only when you login.

I imagine by now you have this solved, but since I ran across this page with the same issue I figured I'd post my solution. Just in case someone else runs across it. I'm new to typescript/nextjs and didn't realize I simply had to create a type definition file to add the role field to session.user
I created /types/next-auth.d.ts
import NextAuth from "next-auth";
declare module "next-auth" {
interface Session {
user: {
id: string;
username: string;
email: string;
role: string;
[key: string]: string;
};
}
}
Then I had to add this to my tsconfig.json
"include": ["next-env.d.ts", "types/**/*.ts", "**/*.ts", "**/*.tsx"],

Related

NextAuth prisma 401 error on deploy but works on localhost

Im having this problem on my deployed app
error:
"\nInvalid `prisma.user.findFirst()` invocation:\n\n\nCan't reach database server at `localhost`:`5432`\n\nPlease make sure your database server is running at `localhost`:`5432`."
ok:
false
status:
401
url:
null
but in my localhost it works perfectly
this is my code:
/pages/api/auth/[...nextauth].js
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaClient } from "#prisma/client";
import bcryptjs from "bcryptjs";
const prisma = new PrismaClient();
export default NextAuth({
session: {
strategy: "jwt",
},
callbacks: {
async jwt({ token, user }) {
if (user?.userId) {
token.userId = user.userId;
}
return token;
},
async session({ session, token }) {
if (token?.userId) {
session.user.userId = token.userId;
}
return session;
},
},
providers: [
CredentialsProvider({
id: "credentials",
name: "Credentials",
authorize: async (credentials) => {
const user = await prisma.user.findFirst({
where: {
email: credentials.email,
},
});
try {
if (
user &&
bcryptjs.compareSync(credentials.password, user.password)
) {
const userInfo = {
userId: user.userId,
name: user.username,
image: user.image,
};
return userInfo;
}
throw new Error("Invalid email or password");
} catch (err) {
const errorMessage = err.response.data.message;
// Redirecting to the login page with error messsage in the URL
throw new Error(errorMessage + "&email=" + credentials.email);
}
},
}),
],
secret: process.env.NEXTAUTH_SECRET,
});
/login
onSubmit={async (values) => {
await signIn("credentials", {
redirect: false,
email: values.email,
password: values.password,
})
.then((error) => console.log(error))
.catch((error) => console.log(error));
}
DATABASE_URL='postgres://postgres:postgres#localhost:5432/nextauth?connect_timeout=300'
NEXTAUTH_URL=my vercel deploy url
NEXTAUTH_SECRET=secret
how can i solve this problem? i tried many things to solve this but it still not working

Updating User Data node.js

I faced into a problem when testing my app: when testing on several accounts, it turned out that the data is added only to the description of the account on which the testing was carried out, even if another user is currently authorized at the moment. When I discovered this, I began to rewrite the code, but nothing happens, I don’t understand what’s wrong, it seems to me that I’m passing the wrong data to user-controller.js and user-service.js
router.js
router.put('/updateUser/:id', userController.update);
controller.js
class UserController {
async updateUser(req, res, next) {
try {
const userUpdate = await userService.update(req);
return res.json(userUpdate);
} catch (e) {
next(e);
}
}
}
service.js
class UserService {
async updateUser(req) {
const userUpdate = await UserModel.findOneAndUpdate(
req.params.id,
req.body.user,
{ new: true }
);
const userDto = new UserDto(userUpdate);
return { user: userDto };
}
}
user-dto.js
module.exports = class UserDto {
email;
id;
description;
constructor(model) {
this.email = model.email;
this.id = model._id;
this.description = model.description
}
}
user-model.js
const UserSchema = new Schema({
email: { type: String, unique: true, required: true },
password: { type: String, required: true },
description: {
city: { type: String },
brand: { type: String },
},
});

NextAuth JS Removing keys from JWT

I am currently using the credentials provider to verify a user on an LDAP. I am also using Hasura as a backend which requires certain claims in the jwt. So a custom encode and decode function is required. This is where i run into my issues. If i used the default encoding for Next-Auth everything works and I am able to log into my app. When i create my own encode and decode function i cannot get past the login screen. I am also using the NextJs middleware to ensure a valid session is present.
Here is my[...nextauth].ts file
export default NextAuth({
providers: [
CredentialsProvider({
id: 'credentials',
name: 'credentials',
credentials: {
username: { label: 'Username', type: 'text', placeholder: '' },
password: { label: 'Password', type: 'password' },
},
async authorize(credentials, req) {
console.log(
`Authorize Function called with creds - ${JSON.stringify(
credentials
)}`
)
//Developement Authentication
if (process.env.RUNNING_ENV == 'DEVELOPMENT')
return {
id: process.env.DEV_USER as string,
group: process.env.DEV_GROUP as string,
}
// const { username, password } = credentials
const username = credentials?.username
const password = credentials?.password
if (!username || !password) {
throw new Error('Enter Username and Password')
}
try {
const response = await authenticate(username, password)
//console.log(`Response: ${JSON.stringify(response)}`)
return { username, group: 'cyberlab' }
} catch (err) {
//console.log(`Error authenticating: ${err}`)
}
return null
},
}),
],
secret: process.env.NEXTAUTH_SECRET,
pages: {
signIn: '/login',
},
//Specifies JSON web tokens will be used.
jwt: {
secret: process.env.JWT_SECRET,
async encode({ token, secret, maxAge }) {
console.log(`Before Encode function token: ${JSON.stringify(token)}`)
const jwtClaims = {
sub: token.username,
name: token.username,
iat: Date.now() / 1000,
exp: Math.floor(Date.now() / 1000) + 3600,
hasura: {
'x-hasura-allowed-roles': [
'CRU',
'Forensic',
'EvSpecialist',
'Preview',
'dany',
],
'x-hasura-default-role': 'dany',
'x-hasura-user-id': token.username,
},
}
const encodedToken = jwt.sign(jwtClaims, secret, {
algorithm: 'HS512',
})
console.log(`Encoded Token: ${JSON.stringify(encodedToken)}`)
return encodedToken
},
async decode({ token, secret }) {
const decodedToken = jwt.verify(token, secret, {
algorithms: ['HS512'],
})
//console.log(`Decoded Token: ${JSON.stringify(decodedToken)}`)
return decodedToken
},
},
callbacks: {
async jwt({ token, user }) {
console.log(`Callback token: ${JSON.stringify(token)}`)
console.log(`Callback user: ${JSON.stringify(user)}`)
// * Hasura required claims will be added here
// TODO check to see if hasura claims exist, if not assign them else just pass the token.
if (user) {
console.log(`Adding User in callback`)
token.username = user.id
token.group = user.group
// token.hasura = {
// 'x-hasura-allowed-roles': [
// 'cru',
// 'forensic',
// 'evSpecialist',
// 'preview',
// 'dany',
// ],
// 'x-hasura-default-role': 'dany',
// 'x-hasura-user-id': token.username,
// }
}
return token
},
async session({ session, token, user }) {
// session.type = token.type
session.name = token.username
session.user = user
session.group = token.group
//console.log(`Session in Callback: ${JSON.stringify(session)}`)
//console.log(`Session type in callback: ${session.type}`)
//console.log(`Session User in callback: ${session.name}`)
return session
},
},
session: {
//Sets the session to use JSON Web Token
strategy: 'jwt',
//Sets the max idle time before token expires in seconds - Currently 1hr
maxAge: 3600,
},
})
Here is my terminal output
Callback token: {"sub":"JDoe"}
Callback user: {"id":"JDoe","group":"DEVELOPMENT"}
Adding User in callback
Before Encode function token: {"sub":"JDoe","username":"JDoe","group":"DEVELOPMENT"}
Encoded Token: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJKRG9lIiwibmFtZSI6IkpEb2UiLCJpYXQiOjE2NDYzMTg2NTMuODA4LCJleHAiOjE2NDYzMjIyNTMsImhhc3VyYSI6eyJ4LWhhc3VyYS1hbGxvd2VkLXJvbGVzIjpbIkNSVSIsIkZvcmVuc2ljIiwiRXZTcGVjaWFsaXN0IiwiUHJldmlldyIsImRhbnkiXSwieC1oYXN1cmEtZGVmYXVsdC1yb2xlIjoiZGFueSIsIngtaGFzdXJhLXVzZXItaWQiOiJKRG9lIn19.lMkiBj6eIKT0CH-6sullN3qO9pDZimKLNfsUSR6G8WUrdtK_DD1kmtmu_nmwpE-RWSkEwSQC-u3g-ocRtrSinQ"
Callback token: {"sub":"JDoe","name":"JDoe","iat":1646318653.808,"exp":1646322253,"hasura":{"x-hasura-allowed-roles":["CRU","Forensic","EvSpecialist","Preview","dany"],"x-hasura-default-role":"dany","x-hasura-user-id":"JDoe"}}
Callback user: undefined
Before Encode function token: {"sub":"JDoe","name":"JDoe","iat":1646318653.808,"exp":1646322253,"hasura":{"x-hasura-allowed-roles":["CRU","Forensic","EvSpecialist","Preview","dany"],"x-hasura-default-role":"dany","x-hasura-user-id":"JDoe"}}
Encoded Token: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NDYzMTg2NTMuODcyLCJleHAiOjE2NDYzMjIyNTMsImhhc3VyYSI6eyJ4LWhhc3VyYS1hbGxvd2VkLXJvbGVzIjpbIkNSVSIsIkZvcmVuc2ljIiwiRXZTcGVjaWFsaXN0IiwiUHJldmlldyIsImRhbnkiXSwieC1oYXN1cmEtZGVmYXVsdC1yb2xlIjoiZGFueSJ9fQ.lPao8tCFq7z0Pb8tIO7sm0L91fkwajA-Uuu_OgG6rIgo4sC3z6Zd07q1XaKNQ0P3-xt2c1bF0up6tVab3djG-g"
Callback token: {"sub":"JDoe","name":"JDoe","iat":1646318653.808,"exp":1646322253,"hasura":{"x-hasura-allowed-roles":["CRU","Forensic","EvSpecialist","Preview","dany"],"x-hasura-default-role":"dany","x-hasura-user-id":"JDoe"}}
Callback user: undefined
Before Encode function token: {"sub":"JDoe","name":"JDoe","iat":1646318653.808,"exp":1646322253,"hasura":{"x-hasura-allowed-roles":["CRU","Forensic","EvSpecialist","Preview","dany"],"x-hasura-default-role":"dany","x-hasura-user-id":"JDoe"}}
Encoded Token: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NDYzMTg2NTUuMjk3LCJleHAiOjE2NDYzMjIyNTUsImhhc3VyYSI6eyJ4LWhhc3VyYS1hbGxvd2VkLXJvbGVzIjpbIkNSVSIsIkZvcmVuc2ljIiwiRXZTcGVjaWFsaXN0IiwiUHJldmlldyIsImRhbnkiXSwieC1oYXN1cmEtZGVmYXVsdC1yb2xlIjoiZGFueSJ9fQ.wnaes7CejSGCjHTzwNKTsNV3pfhy4iYqyRmfaNhpELQvJDciYMfTyFc2O4byq8cLAP2brUpfDwyQZIFZNMAGPA"
Callback token: {"iat":1646318655.297,"exp":1646322255,"hasura":{"x-hasura-allowed-roles":["CRU","Forensic","EvSpecialist","Preview","dany"],"x-hasura-default-role":"dany"}}
Callback user: undefined
Before Encode function token: {"iat":1646318655.297,"exp":1646322255,"hasura":{"x-hasura-allowed-roles":["CRU","Forensic","EvSpecialist","Preview","dany"],"x-hasura-default-role":"dany"}}
Encoded Token: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NDYzMTg2NTUuNzQ3LCJleHAiOjE2NDYzMjIyNTUsImhhc3VyYSI6eyJ4LWhhc3VyYS1hbGxvd2VkLXJvbGVzIjpbIkNSVSIsIkZvcmVuc2ljIiwiRXZTcGVjaWFsaXN0IiwiUHJldmlldyIsImRhbnkiXSwieC1oYXN1cmEtZGVmYXVsdC1yb2xlIjoiZGFueSJ9fQ.6saQlySc7rgHikj85iejpz6nRm9fEtEdupz_j1hcwZ0TcZiQlLvY1-M-9xkju2F-0MlWmQwIj-bfEU7BmuEc5w"
Callback token: {"iat":1646318655.297,"exp":1646322255,"hasura":{"x-hasura-allowed-roles":["CRU","Forensic","EvSpecialist","Preview","dany"],"x-hasura-default-role":"dany"}}
Callback user: undefined
Before Encode function token: {"iat":1646318655.297,"exp":1646322255,"hasura":{"x-hasura-allowed-roles":["CRU","Forensic","EvSpecialist","Preview","dany"],"x-hasura-default-role":"dany"}}
Encoded Token: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NDYzMTg2NTUuOTgsImV4cCI6MTY0NjMyMjI1NSwiaGFzdXJhIjp7IngtaGFzdXJhLWFsbG93ZWQtcm9sZXMiOlsiQ1JVIiwiRm9yZW5zaWMiLCJFdlNwZWNpYWxpc3QiLCJQcmV2aWV3IiwiZGFueSJdLCJ4LWhhc3VyYS1kZWZhdWx0LXJvbGUiOiJkYW55In19.0tqw2fg_GjQGY55sHCKxscipHaGj9IHrdgNKBETsOzMPn5Rai3CFx1TMJP9ZOcyAzbSBmrXN31uWKCrda37X_g"
Here is what my middleware currently looks like.
import { NextApiRequest } from 'next'
import { getToken } from 'next-auth/jwt'
import { NextResponse, NextRequest } from 'next/server'
//Groups and Pages Associated with groups
// const userGroups = [
// 'CRU',
// 'Forensic',
// 'Evidence Specialist',
// 'Preview',
// 'Dany',
// 'DEVELOPMENT',
// 'TEST',
// ]
//Group access pages.
const CRU_PAGES: string[] = ['']
const FORENSIC_PAGES: string[] = ['']
const EVSPEVIALIST_PAGES: string[] = ['']
const PREVIEW_PAGES: string[] = ['']
const DANY_PAGES: string[] = ['']
const DEV_PAGES: string[] = ['/testpages', '/testpage', '/cases']
const TEST_PAGES: string[] = ['/testpage']
//Default Access Routes
const DEFAULT_PAGES: string[] = [
'/',
'/unauthorized',
'/api',
'/favicon.ico',
'/login',
]
//The following function will protect the routes or redirect to unauthorized if not allowed to access a page.
function checkAuthPath(pathname: string, group: string, req: NextApiRequest) {
var authorizedPages: string[] = ['']
//Based on group assign authorized pages to the authorizedPages array.
switch (group) {
case 'CRU':
authorizedPages = CRU_PAGES
break
case 'Forensic':
authorizedPages = FORENSIC_PAGES
break
case 'Evidence Specialist':
authorizedPages = EVSPEVIALIST_PAGES
break
case 'Preview':
authorizedPages = PREVIEW_PAGES
break
case 'Dany':
authorizedPages = DANY_PAGES
break
case 'DEVELOPMENT':
authorizedPages = DEV_PAGES
break
default:
authorizedPages = TEST_PAGES
}
authorizedPages = authorizedPages.concat(DEFAULT_PAGES)
//Determine if request path is in the authorized paths Array. If not redirect to unauthorized.
if (authorizedPages.includes('/' + pathname.split('/')[3])) {
//console.log(`pathname in checkauth function: ${pathname}`)
//console.log('Authorized')
return NextResponse.next()
} else {
//console.log('Unauthorized')
return NextResponse.redirect(new URL('/unauthorized', req.url))
}
}
export async function middleware(req: NextApiRequest) {
const token = await getToken({ req, secret: process.env.JWT_SECRET })
// console.log(`Middleware Token: ${JSON.stringify(token)}`)
const pathname = req.url
if (typeof pathname === 'string') {
if (pathname.includes('/api/auth') || token) {
if (token) {
//console.log('Token Found')
//console.log(`pathname: ${pathname}`)
const group = token.group as string
return checkAuthPath(pathname, group, req)
} else return NextResponse.next()
}
if (
(!token && pathname !== 'http://localhost:3000/login') ||
pathname.includes('/api/auth')
) {
//&& !pathname.includes('/api/auth/signin'
//console.log('Token Not Found')
return NextResponse.redirect(new URL('/login', req.url))
}
} else {
throw new Error('Pathname Undefined')
}
}
As you can see by the last output i am missing then user and group from the JWT. Also why does it loop so many times?
Solved by including the custom encoding and decoding in the middleware too.

Error: Request failed with status code 404 , Axios trying to fetch github user emails using passport-github2

const Raven = require('raven')
const GithubStrategy = require('passport-github2').Strategy
const axios = require('axios');
const models = require('../../../db/models').models
const config = require('../../../../config')
const secrets = config.SECRETS
const debug = require('debug')('oauth:strategies:github')
const { generateReferralCode } = require('../../../utils/referral')
/**
* Authenticate _users_ using their Github Accounts
*/
module.exports = new GithubStrategy({
clientID: secrets.GITHUB_CONSUMER_KEY,
clientSecret: secrets.GITHUB_CONSUMER_SECRET,
callbackURL: config.SERVER_URL + config.GITHUB_CALLBACK,
passReqToCallback: true,
}, async function (req, token, tokenSecret, profile, cb) {
let profileJson = profile._json
console.log(profileJson);
try{
const config = {method:'get',headers:{'Authorization':`Bearer ${token}`}};
const result = await axios.get('https://api.github.com/user/emails',config);
let emailArr = result.data;
let primaryGithubEmail = emailArr.filter((email)=>{return email.primary;});
profileJson.email = primaryGithubEmail[0].email;
}catch(error){
console.log(error);
}
console.log('======== profile after request ============');
console.log(profileJson);
console.log('====================');
let oldUser = req.user
Raven.setContext({ extra: { file: 'githubstrategy' } })
try {
if (oldUser) {
debug('User exists, is connecting Github account')
/*
This means an already logged in users is trying to
connect Github to his account. Let us see if there
are any connections to his Github already
*/
const ghaccount = await models.UserGithub.findOne({ where: { id: profileJson.id } })
if (ghaccount) {
throw new Error('Your Github account is already linked with codingblocks account Id: ' + ghaccount.get('userId'))
} else {
await models.UserGithub.upsert({
id: profileJson.id,
token: token,
tokenSecret: tokenSecret,
username: profileJson.login,
userId: oldUser.id
})
const user = await models.User.findById(oldUser.id)
if (user) {
return cb(null, user.get())
} else {
return cb(null, false, { message: "Could not retrieve existing Github linked account" })
}
}
} else {
/*
This means either -
a. This is a new signup via Github
b. Someone is trying to login via Github
*/
let userGithub = await models.UserGithub.findOne({
include: [models.User],
where: { id: profileJson.id }
})
/*
If userGithub exists then
Case (a): login
*/
if (!userGithub) {
/*
If there is any user with verified email equal to the email comming from github strategy , then create a new entry in userGithub table and login that user
*/
const userWithVerifiedEmail = await models.User.findOne({
where: {
verifiedemail: profileJson.email
}
})
if (userWithVerifiedEmail) {
userGithub = await models.UserGithub.create({
id: profileJson.id,
token: token,
tokenSecret: tokenSecret,
username: profileJson.login,
userId: userWithVerifiedEmail.get('id'),
})
return cb(null, userWithVerifiedEmail.get());
}
/*
Case (b): New Signup
First ensure there aren't already users with the same email
id that comes from Github
*/
let existingUsers = [];
if (profileJson.email) {
existingUsers = await models.User.findAll({
include: [{
model: models.UserGithub,
attributes: ['id'],
required: false
}],
where: {
email: profileJson.email,
'$usergithub.id$': { $eq: null }
}
})
}
if (existingUsers && existingUsers.length > 0) {
let oldIds = existingUsers.map(eu => eu.id).join(',')
return cb(null, false, {
message: `
Your email id "${profileJson.email}" is already used in the following Coding Blocks Account(s):
[ ${oldIds} ]
Please log into your old account and connect Github in it instead.
Use 'Forgot Password' option if you do not remember password of old account`
})
}
/* Check if users with same username exist. Modify username accordingly */
const existCount = await models.User.count({ where: { username: profileJson.login } })
userGithub = await models.UserGithub.create({
id: profileJson.id,
token: token,
tokenSecret: tokenSecret,
username: profileJson.login,
user: {
username: existCount === 0 ? profileJson.login : profileJson.login + "-gh",
firstname: profileJson.name ? profileJson.name.split(' ')[0] : profileJson.login,
email: profileJson.email,
referralCode: generateReferralCode(profileJson.email).toUpperCase(),
photo: profileJson.avatar_url,
verifiedemail: profileJson.email,
marketing_meta: req.session.marketingMeta
}
}, {
include: [models.User],
})
req.visitor.event({
ea: 'successful',
ec: 'signup',
el: 'github'
}).send()
req.session.isNewSignup = true
if (!userGithub) {
return cb(null, false, { message: 'Authentication Failed' })
}
}
return cb(null, userGithub.user.get())
}
} catch (err) {
Raven.captureException(err)
cb(null, false, { message: err.message })
}
})
when I am running this code locally on my system , its working fine , but as soon as I am sending the code to the staging and production i am getting the error
{ Error: Request failed with status code 404
0|oneauth | at createError (/home/codingblocks/servers/khaate/node_modules/axios/lib/core/createError.js:16:15)
0|oneauth | at settle (/home/codingblocks/servers/khaate/node_modules/axios/lib/core/settle.js:17:12)
0|oneauth | at IncomingMessage.handleStreamEnd (/home/codingblocks/servers/khaate/node_modules/axios/lib/adapters/http.js:236:11)
0|oneauth | at IncomingMessage.emit (events.js:203:15)
0|oneauth | at IncomingMessage.EventEmitter.emit (domain.js:466:23)
0|oneauth | at IncomingMessage.wrapped (/home/codingblocks/servers/khaate/node_modules/newrelic/lib/transaction/tracer/index.js:188:22)
...............
I am not able to understand why this error is comming and I am also not able to get the user emails , but locally this code works fine and I am able to fetch all the emails associated with the github of the user.

View is rendered before user type is loaded from firestore

So I'm building an Ionic - Angular app that have an hospital patient submit a request to the nurse stuff and the nurse stuff can see their assigned requests (based on the room that assigned to the patient submitting the request). A nurse can see all requests and a patient can see only his/her requests. I have a function in the auth.service.ts that is called (setUserType() ) once a user is logged in manually or if it is an auto login(token is stored and found) and fetch the user type and name once it finished authentication.
The problem is, in the my-requests.page.ts in NgOnInit I call a function in the requests service that run a query to fetch all requests(if it is a nurse) or to fetch only the user's requests(if it is a patient) based on the user type I assigned once login/auto login occured. This field is unassigned once the my-requests.page.html is rendered and I can't seem to find a way to make it render only after I have the user type information.
setUserType() function:
let userId: string;
this.userIdObservable.subscribe(x => {
userId = x;
});
const userQuery = this.firestore.doc<Users>(`added-users/${userId}`);
userQuery.valueChanges().subscribe(x => {
this._userType = x.type;
this._userName = x.name;
});
My requests ngOnInit function:
ngOnInit() {
this.segment.value = 'progress';
this.requestSubscription = this.requestsService
.loadRequests()
.subscribe(requests => {
this.requestsList = requests;
});
}
Now all the auth functions -
Auth page Authenticate function:
authenticate(email: string, password: string) {
this.isLoading = true;
this.loadingCtrl
.create({
keyboardClose: true,
message: 'Logging in...'
})
.then(loadingEl => {
loadingEl.present();
let authObs: Observable<AuthResponseData>;
if (this.isLogin) {
authObs = this.authService.login(email, password);
} else {
authObs = this.authService.signup(email, password);
}
authObs.subscribe(resData => {
console.log(resData);
this.isLoading = false;
loadingEl.dismiss();
this.authService.setUserType();
this.router.navigateByUrl('/requests/tabs/add-requests');
}, errRes => {
loadingEl.dismiss();
const code = errRes.error.error.message;
let message = 'Could not sign you up, please try again.';
if (code === 'EMAIL_EXISTS') {
message = 'This Id exists already!';
} else if (code === 'EMAIL_NOT_FOUND') {
message = 'No such user.';
} else if (code === 'INVALID_PASSWORD') {
message = 'Could not log you in, please try again.';
}
this.showAlert(message);
});
});
}
Auth service login function:
login(email: string, password: string) {
return this.http
.post<AuthResponseData>(
`https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=${
environment.firebaseAPIKey
}`,
{ email: email, password: password, returnSecureToken: true }
)
.pipe(tap(this.setUserData.bind(this)));
}
Auth service autologin function:
autoLogin() {
return from(Plugins.Storage.get({ key: 'authData' })).pipe(
map(storedData => {
if (!storedData || !storedData.value) {
return null;
}
const parsedData = JSON.parse(storedData.value) as {
token: string;
tokenExpirationDate: string;
userId: string;
email: string;
};
const expirationTime = new Date(parsedData.tokenExpirationDate);
if (expirationTime <= new Date()) {
return null;
}
const user = new User(
parsedData.userId,
parsedData.email,
parsedData.token,
expirationTime
);
return user;
}),
tap(user => {
if (user) {
this._user.next(user);
this.setUserType();
}
}),
map(user => {
return !!user;
})
);
}
This is how you can do you dont have to include it in any module cli will do that for you.
import {Component, Injectable, OnInit} from '#angular/core';
import {BehaviorSubject} from 'rxjs';
import {FormGroup} from '#angular/forms';
#Injectable({
providedIn: 'root'
})
export class UserStateService {
private user = new BehaviorSubject({
isLoggedIn: false,
userType: null
});
constructor() {
}
setUser(user) {
this.user.next(user);
}
getUser() {
return this.user;
}
}
// my request
#Component({
selector: 'request-component',
templateUrl: './request-component.html'
})
export class RequestComponent implements OnInit {
constructor(private userStateService: UserStateService) {}
ngOnInit(): void {
this.userStateService
.getUser()
.subscribe(
((val: {isLoggedIn: boolean, userType: any}) => {
// calll you service
}));
}
}
// in your auto login or login you call setter
this.userStateService.setUser({isLoggedIn: true, userType: 'data from login'});

Categories