I am trying to develop a mail sending module in my NestJs project. when I send the mail through my local machine it works fine. But when it goes to the server (digital-ocean droplet) it throws the following error and it does not send any email further. what is going on and fix this?
My code segment is below:
Auth controller
#Post('register')
async register(#Body() register: RegisterRequest) {
const res = await this.authService.register(register);
if (res instanceof Error) {
throw res;
}
return {
statusCode: 200,
message:
'Your account is registered successfully. Please check your email to verify your account',
};
}
Auth Service
async register(register: RegisterRequest): Promise<any> {
register.isRegister = true;
register.status = 0;
register.roleId = 5;
const user = await this.userService.save(register);
console.log('User Saved');
if (user instanceof User) {
if (register.isRegister) {
console.log('IS REGISTER');
// Generate Token
const resultsToken = await this.userTokenService.save(user.id, 1);
console.log('USER TOKEN SAVED');
if (resultsToken) {
this.mailService.sendUserConfirmation(user, resultsToken.token);
}
}
}
return user;
}
User Service
async save(register: RegisterRequest): Promise<User> {
try {
const token = generateToken(8);
const user = new User();
user.email = register.email;
user.firstName = register.firstName;
user.lastName = register.lastName;
user.password = hashPassword(register.password || token);
user.role = register.roleId;
user.phoneNumber = register.phoneNumber;
user.isActive = register.status;
const errors = await validate(user);
if (errors.length > 0) {
throw new ParameterMissingException(
errors[0].constraints[Object.keys(errors[0].constraints)[0]],
);
}
const existing = await this.findOneByEmail(register.email);
if (existing) {
throw new EntityFoundException('Email');
}
const registered = await this.userRepository.save(user);
return registered;
} catch (error) {
return error;
}
}
User Token service
async save(userId: number, type: number): Promise<UserToken> {
try {
const userToken = new UserToken();
userToken.user = userId;
userToken.type = type;
userToken.token = generateToken();
if (type === 2) {
userToken.expireIn = 15;
}
console.log('USER TOKEN SAVE');
return await this.userTokenRepository.save(userToken);
} catch (error) {
console.log('USER TOKEN ERROR');
return error;
}
}
Mail Service
sendUserConfirmation(user: any, token: string) {
const url = `${
this.configService.get<string>('REGISTER_CONFIRM_URL') + token
}`;
console.log('MAIL SERVICE ' + url);
this.mailerService
.sendMail({
to: user.email,
// from: '"Support Team" <support#example.com>', // override default from
subject: 'Greetings from CEWAS!',
template: join(__dirname, 'templates') + './register-confirmation',
context: {
url,
},
})
.then((r) => console.log(r))
.catch((err) => {
console.log('MAIL SERVICE ERROR');
console.log(err);
});
}
Mail Module and Config
import { MailerModule } from '#nestjs-modules/mailer';
import { HandlebarsAdapter } from '#nestjs-
modules/mailer/dist/adapters/handlebars.adapter';
import { Module } from '#nestjs/common';
import { MailService } from './mail.service';
import { join } from 'path';
#Module({
imports: [
MailerModule.forRoot({
transport: {
service: 'gmail',
secure: true,
auth: {
user: '********#gmail.com',
pass: '********',
},
},
defaults: {
from: '"<No Reply>" <*******#gmail.com>',
},
template: {
dir: join(__dirname, 'templates'),
adapter: new HandlebarsAdapter(),
options: {
strict: true,
},
},
}),
],
providers: [MailService],
exports: [MailService],
})
export class MailModule {}
Hi try whit this configuration in your transport:
transport: {
host: 'smtp.gmail.com',
port: 465,
ignoreTLS: true,
secure: true,
auth: {
user: '********#gmail.com', //use the .env variable here for security
pass: '********'
},
}
and make sure you turned on access for less secure app
here the link: less secure app
Related
i am recieving Error: Error occurred while verifying paramssubVerifierParams need to equal threshold 1
web3auth.ts
import { Web3Auth } from '#web3auth/node-sdk';
import { CHAIN_NAMESPACES, SafeEventEmitterProvider } from '#web3auth/base';
import { WEB3AUTH } from '../config/globals';
import logger from '../config/logger';
export const web3auth = new Web3Auth({
clientId: WEB3AUTH.clientId,
chainConfig: {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: WEB3AUTH.chainId,
rpcTarget: WEB3AUTH.rpcTarget,
displayName: 'Polygon Mainnet',
blockExplorer: 'https://polygonscan.com',
ticker: 'MATIC',
tickerName: 'Matic',
},
web3AuthNetwork: process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet',
});
export const connect = async (token: string): Promise<void> => {
try {
const provider = (await web3auth.connect({
verifier: WEB3AUTH.verifier, // replace with your verifier name
verifierId: WEB3AUTH.verifierId, // replace with your verifier id, setup while creating the verifier on Web3Auth's Dashboard
idToken: token, // replace with your newly created unused JWT Token.
subVerifierInfoArray: [
{
verifier: 'ga-google',
idToken: token,
},
{
verifier: 'zt-email',
idToken: token,
},
],
})) as SafeEventEmitterProvider;
if (!provider) logger.error('error');
const ethPrivKey = await provider.request({ method: 'eth_private_key' });
logger.info('ETH Private Key', ethPrivKey);
} catch (error) {
throw error;
}
};
controller.ts
web3authHandler = asyncHandler(async (req: Request, res: Response, next: NextFunction) => {
try {
web3auth.init();
const accessToken: string = res.locals.accessToken;
const data = await connect(accessToken);
console.log('data: ', data);
return new SuccessResponse('Successful web3auth', { data }).send(res);
} catch (error) {
throw error;
}
});
What should i do now? I am completely stuck here. Also provide me with more insights of web3auth. What should I use as the verifier and verifierId?
I'm working on the user registration functionality of an application using Typescript and Redux Toolkit. When I make the fetch request to the signup endpoint, a new user is saved to the database I've connected, but I keep entering the catch error block.
export const registerUser = createAsyncThunk(
"user/registerUser",
async (form: { username:string, password:string }, thunkAPI) => {
try {
const response = await fetch('/api/auth/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userInfo: {
username: form.username,
password: form.password
}
}),
});
if (response.status === 200) return 200;
else return 400;
} catch (e) {
console.log('Error')
}
}
);
I've tried logging the response to the console a number of ways
const data = await response.json() console.log(data)
But have had no luck. I think this is an error with how I've done my fetch request using createAsyncThunk but haven't been able to figure out what I've missed.
This is the code for the initial state and slice:
interface UserState {
userProfile: {
id: number | null;
},
registration: {
status: 'loaded' | 'loading'
}
}
const initialState : UserState = {
userProfile: {
id: null,
},
registration: {
status: 'loaded'
}
};
export const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
},
extraReducers: (builder) => {
builder.addCase(registerUser.fulfilled, (state) => { state.registration.status = 'loaded' }),
builder.addCase(registerUser.rejected, (state) => { state.registration.status = 'loaded' }),
builder.addCase(registerUser.pending, (state) => { state.registration.status = 'loading' })
}
})
And here is the code for the function where the action is dispatched on the UI
const handleRegister= async () => {
if (!username) return alert('Username field was left empty');
if (!password) return alert('Password field was left empty');
const {payload} : any = await dispatch(registerUser({ username: username, password: password}));
if (payload === 200) {
alert('Successfully registered. Redirecting to dashboard');
return navigate('/dashboard');
} else { return alert('User creation unsuccessful'); }
}
Appreciate any help as I've looked through many other posts but haven't been able to resolve my issue.
Hi i am trying to setup LDAP authentication for my meteorJS app and i am following the steps listed in here https://janikvonrotz.ch/2017/02/08/meteor-register-ldap-login-request-handler/
i changed the search filter from mail to username and pushed everything inside of Meteor.startup() here is my code set up
UI code written in /imports/ui/loginform.jsx
let loginUserWithLDAP = (username, password, callback) => {
var loginRequest = {
ldap: true,
username: username,
email: username+"#company.com",
pass: password,
}
Accounts.callLoginMethod({
methodArguments: [loginRequest],
userCallback: callback
})
}
in my /server/ldap.js
Meteor.startup(() => {
var ldapAuth = {
url: 'ldap://company.com:389',
searchOu: 'ou=Employees,ou=\'company Users\', dc=company,dc=com',
searchQuery: (username) => {
return {
filter: '(&(objectclass=user)(samaccountname='+username+'))',
scope: 'sub'
}
}
}
ldapAuth.checkAccount = (options) => {
options = options || {}
ldapAuth.client = ldap.createClient({
url: ldapAuth.url
})
let dn = ['company', 'com']
var future = new Future()
ldapAuth.client.search(
ldapAuth.searchOu,
ldapAuth.searchQuery(options.username),
(error, result)=> {
assert.ifError(error)
result.on('searchEntry', (entry) => {
dn.push(entry.objectName)
return ldapAuth.profile = {
firstname: entry.object.cn,
lastname: entry.object.sn
}
})
result.on('error', function(error){
throw new Meteor.Error(500, "LDAP server error")
})
result.on('end', function(){
if (dn.length === 0) {
future['return'](false)
return false
}
return ldapAuth.client.bind(dn[0], options.pass, (error) =>{
if (error){
future['return'](false)
return false
}
return ldapAuth.client.unbind((error) => {
assert.ifError(error)
return future['return'](!error)
});
})
})
})
return future.wait()
}
Accounts.registerLoginHandler('ldap', (loginRequest)=>{
if (!loginRequest.ldap) {
return undefined
}
if (ldapAuth.checkAccount(loginRequest)){
var userId = null
var user = Meteor.users.findOne({"username": loginRequest.username })
if (!user) {
userId = Accounts.createUser({
username: loginRequest.username,
password: loginRequest.pass,
profile: ldapAuth.profile,
roles: ['user'],
})
Meteor.users.update(userId, { $set: { 'emails.0.verified': true } })
} else {
userId = user._id
}
let stampedToken = Accounts._generateStampedLoginToken()
let hashStampedToken = Accounts._hashStampedToken(stampedToken)
Meteor.users.update(userId,
{ $push: {'services.resume.loginTokens': hashStampedToken } }
)
return {
userId: userId,
token: stampedToken.token
}
}
})
});
In my debugging i found that its erroring out at
result.on('error', function(error){
throw new Meteor.Error(500, "LDAP server error")
})
due to '000004DC: LdapErr: DSID-0C0907E9, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v2580' what does this mean?
What is my code missing?
In short you need to define a search user that does the binding with the LDAP directory.
The post is outdated, I've got you this example: https://github.com/janikvonrotz/Zenkom/blob/0583f01abca96847178a248ff446d84c754965e9/server/actions/ldap.js#L18
Setup the search user like this:
"searchUser": {
"dn": "CN=username,OU=org,DC=company,DC=ch",
"password": "password"
}
The bind user is simply for search the directory. Another bind is executed to authenticate the found user.
I am new to NuxtJS and have a problem, I am trying to get the token of the user who logged in from the website, the token is stored in the cookie, but, when I start or reload the website page (made with nuxt ssr (universal )), nuxtServerInit should and does start, but req.headers.cookie says it is undefined, so the data cannot be loaded into the store. If I reload the page, the cookie is still in the browser and everything is perfect, the problem is that the req.headers.cookie is: undefined, why? Ahhh, and in development it works perfectly, but in production it doesn't work (in nuxtServerInit the req.headers.cookie is not defined)
I am using Firebase Hosting, Cloud Features, Authentication, Cloud Firestore.
Here is the code:
// store/index.js
import { getUserFromCookie, getUserFromSession } from '../helpers/index.js'
export const actions = {
async nuxtServerInit({ app, dispatch }, { req, beforeNuxtRender }) {
console.log('req.headers.cookie: ' + req.headers.cookie)
console.log('req.session: ', req.session)
if (process.server) {
const user = getUserFromCookie(req)
console.log('process.server: ' + process.server)
console.log('user: ', user)
if (user) {
await dispatch('modules/user/setUSER', {
name: !!user.name ? user.name : '',
email: user.email,
avatar: !!user.picture ? user.picture : '',
uid: user.user_id
})
await dispatch('modules/user/saveUID', user.user_id)
} else {
await dispatch('modules/user/setUSER', null)
await dispatch('modules/user/saveUID', null)
}
}
}
}
// helpers/index.js
import jwtDecode from 'jwt-decode'
var cookieparser = require('cookieparser')
export function getUserFromCookie(req) {
if(req.headers.cookie){
const parsed = cookieparser.parse(req.headers.cookie)
const accessTokenCookie = parsed.access_token
if (!accessTokenCookie) return
const decodedToken = jwtDecode(accessTokenCookie)
if (!decodedToken) return
return decodedToken
}
return null
}
// pages/auth/signup.vue
<script>
import { mapActions } from 'vuex'
export default {
data () {
return {
email: '',
password: '',
renderSource: process.static ? 'static' : (process.server ? 'server' : 'client')
}
},
middleware: ['handle-login-route'],
methods: {
...mapActions('modules/user', [ 'login' ]),
async signUp () {
try {
const firebaseUser = await this.$firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
await this.writeUserData(firebaseUser.user.uid, firebaseUser.user.email)
await this.login(firebaseUser.user)
this.$router.push('/protected')
} catch (error) {
console.log(error.message)
}
},
writeUserData (userId, email) {
const db = this.$firebase.firestore()
return db.collection("Usuarios").doc(userId).set({
email: email
})
}
}
}
</script>
// store/modules/user.js
export const actions = {
async login({ dispatch, state }, user) {
console.log('[STORE ACTIONS] - login')
const token = await this.$firebase.auth().currentUser.getIdToken(true)
const userInfo = {
name: user.displayName,
email: user.email,
avatar: user.photoURL,
uid: user.uid
}
Cookies.set('access_token', token) // saving token in cookie for server rendering
await dispatch('setUSER', userInfo)
await dispatch('saveUID', userInfo.uid)
console.log('[STORE ACTIONS] - in login, response:', status)
},
async logout({ commit, dispatch }) {
console.log('[STORE ACTIONS] - logout')
await this.$firebase.auth().signOut()
Cookies.remove('access_token');
commit('setUSER', null)
commit('saveUID', null)
},
saveUID({ commit }, uid) {
console.log('[STORE ACTIONS] - saveUID')
commit('saveUID', uid)
},
setUSER({ commit }, user) {
commit('setUSER', user)
}
}
Thanks a lot! :D
if you are hosting it on Firebase you should rename your cookie to "__session", that's the only name you could use on Firebase. Their documentation should make it very clear!
Change the following part:
// helpers/index.js
const parsed = cookieparser.parse(req.headers.cookie)
const accessTokenCookie = parsed.__session
// store/modules/user.js
Cookies.set('__session', token)
I have added an AuthGuard on the UsersController class but I want to exclude one method in this controller from authorization.
Is it possible to exclude a single method from authorization?
I have added my code below:
#UseGuards(AuthGuard('jwt'))
#ApiUseTags('Users')
#Controller('users')
export class UsersController {
constructor(public service: UsersService) {}
get base(): CrudController<UsersService, UserEntity> {
return this;
}
#Override()
async createOne(#ParsedParams() params, #ParsedBody() body: UserEntity) {
const username = body.username, email = body.email;
const qb = await getRepository(UserEntity)
.createQueryBuilder('users')
.where('users.username = :username', { username })
.orWhere('users.email = :email', { email });
const _user = await qb.getOne();
if (_user) {
const error = { username: 'username already exists' };
throw new HttpException({ message: 'Input data validation error', error }, HttpStatus.BAD_REQUEST);
}
return this.base.createOneBase(params, body);
}
#Post(':id/avatar')
#UseInterceptors(FileInterceptor('file', {
storage: multerDiskStorageConfig('users', 'avatar'),
}))
async uploadAvatarFile(#Param() params, #UploadedFile() file: any) {
const userObject = await this.base.service.findOne();
userObject.avatar = file.path.replace(PUBLIC_ROOT_PATH, '');
return this.base.updateOneBase(params, userObject);
}
}