How to disable assess to login page once login is completed - node.js

How can i block access to the pages once login has been completed in VueJS.
Also how can i display my server validation errors using bootstrap invalid-feedback class?
Please comment if you have any questions regarding my code or want me to clarify anything more in-depth.
<template>
<div>
<div class="h-100 bg-plum-plate bg-animation">
<div class="d-flex h-100 justify-content-center align-items-center">
<b-col md="8" class="mx-auto app-login-box">
<div class="app-logo-inverse mx-auto mb-3"/>
<div class="modal-dialog w-100 mx-auto">
<div class="modal-content">
<div class="modal-body">
<div class="h5 modal-title text-center">
<h4 class="mt-2">
<div>Welcome back,</div>
<span>Please sign in to your account below.</span>
</h4>
</div>
<b-form-group id="Admin Email" label-for="Admin Email">
<b-form-input
id="Admin Email"
type="email"
required
placeholder="Enter email..."
v-model="email">
</b-form-input>
<div class="invalid-feedback">
{{errorMsg}}
</div>
</b-form-group>
<b-form-group
id="Admin Password"
label-for="Admin Password"
>
<b-form-input
id="Admin password"
type="password"
required
placeholder="Enter password..."
v-model="password"
></b-form-input>
<div class="invalid-feedback">
{{errorMsg}}
</div>
</b-form-group>
<b-form-checkbox name="check" id="exampleCheck">
Keep me logged in
</b-form-checkbox>
<div class="divider"/></div>
<div class="modal-footer clearfix">
<div class="float-left">
<a
href="javascript:void(0);"
class="btn-lg btn btn-link"
>
Recover Password</a>
</div>
<div class="float-right">
<b-button variant="primary" size="lg" #click="signin">
Login to Dashboard
</b-button>
</div>
</div>
</div>
</div>
<div class="text-center text-white opacity-8 mt-3"></div>
</div>
</div>
</b-col>
</div>
</div>
</div>
</template>
<script>
import Authentication from '../../services/authenticationService.js'
import {store} from '../../store.js'
export default {
name: 'HelloWorld',
data () {
return {
email: '',
password: '',
store: store.state.login,
errorMsg: '',
stored: store
}
},
methods: {
async signin () {
try{
const login = await Authentication.login({
email: this.email,
password: this.password
})
var secured = login.data.token.split(' ')[1]
sessionStorage.setItem('jwt', login.data.token)
if (sessionStorage.getItem('jwt') != null || sessionStorage.getItem('jwt') == login.data.token)
{
this.stored.isLoggedIn()
this.$router.push('/admin')
} else {
this.$router.push('/admin/login')
}
}
catch(err){
if(err.response){
this.errorMsg = err.response.data.message
}else if(err.request){
this.errorMsg = err.request
}else{
this.errorMsg = err.message
}
this.errorMsg = err;
}
}
}
}
</script>

You can either check in the created hook, or check in the beforeRouteEnter guard.
You could also check this out for a third option which uses beforeEach
Login.vue - Using the created hook
<script>
export default {
created() {
if(/* If logged in */){
this.$router.push('/admin')
}
}
}
</script>
Using beforeRouteEnter
<script>
import { store } from '../../store'
export default {
beforeRouteEnter(to, from, next) {
if(/* Check store if logged in */){
next('/admin')
} else {
next()
}
}
}
</script>

Related

Render updated document to ejs page mongoose node js

I have an app where users can create an account and update their information after creation. I am able to save the updated document to the database when users input new information on the edit page, however, when I redirect them to the user panel, the old information is still being displayed. I believe that it has something to do with the session that gets created on login because the updated information only shows once the user logs out and logs back in.
This is my edit page:
<%- include('partials/header') %>
<% if(user.firstName.endsWith("s")) { %>
<h1 class="dashboard-title"><%=user.firstName + "' Account"%></h1>
<% } else { %>
<h1 class="dashboard-title"><%=user.firstName + "'s Account"%></h1>
<% } %>
<!-- Action Buttons -->
<div class="container">
<div class="row justify-content-center">
<div class="col-md-3">
<a href="/logout" class="dashboard-btn">
<h5>Logout <i class="fas fa-door-open"></i></h5>
</a>
</div>
<div class="col-md-3">
<a href="/edit" class="dashboard-btn">
<h5>Edit <i class="fas fa-edit"></i></h5>
</a>
</div>
</div>
</div>
<br>
<!-- Information -->
<div class="container">
<form class="" action="/edit" method="post">
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="firstName">First Name:</label>
<div class="form-group col-md-7">
<input name="firstName" class="form-control" type="text" value="<%=user.firstName%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="lastName">Last Name:</label>
<div class="form-group col-md-7">
<input name="lastName" class="form-control" type="text" value="<%=user.lastName%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="email">Email:</label>
<div class="form-group col-md-7">
<input name="email" class="form-control" type="text" value="<%=user.username%>" readonly>
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="phone">Phone:</label>
<div class="form-group col-md-7">
<input name="phone" class="form-control" type="text" value="<%=user.phoneNumber%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="address">Address:</label>
<div class="form-group col-md-7">
<input name="address" class="form-control" type="text" value="<%=user.personalInfo.address%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="coverage">Coverage:</label>
<div class="form-group col-md-7">
<input name="coverage" class="form-control" type="text" value="<%=user.coverage%>" >
</div>
</div>
<br>
<div class="row justify-content-center">
<label class="col-form-label col-md-1" for="paymentPlan">Payment:</label>
<div class="form-group col-md-7">
<input name="paymentPlan" class="form-control" type="text" value="<%=user.paymentPlan%>">
</div>
</div>
<br>
<button class="btn register-btn" type="submit">Submit Changes</button>
</form>
</div>
<%- include('partials/footer') %>
And app.js to handle the post requests to edit route:
app.get("/user-panel", function(req, res) {
if(req.isAuthenticated()) {
res.render("user-panel", {
user: req.user
});
} else {
res.redirect('/login');
}
});
app.get("/edit", function(req, res) {
if(req.isAuthenticated()) {
res.render("edit", {
user: req.user
});
} else {
res.redirect("/login");
}
});
app.post("/edit", function(req, res) {
const email = req.user.username;
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const phone = req.body.phone;
User.findOne({username: email}, function(err, foundUser) {
if(err) {
console.log(err);
} else {
if (foundUser) {
foundUser.firstName = firstName;
foundUser.save();
res.redirect("/user-panel");
}
}
});
});
Any ideas on how I can get the server to respond with the updated info without having to log out the user?
I want to touch on a few things.
to answer your question, you need to query the database again upon redirect. like so:
you need to pass the email value back to the original user-panel function:
res.redirect("/user-panel?username=" + email);
then, you have to query the database again, like so:
app.get("/user-panel", authCheck, function(req, res) {
let email = req.query.email
User.findOne({username: email}, function(err, foundUser) {
if(err) {
console.log(err);
} else {
if (foundUser) {
foundUser.firstName = firstName;
foundUser.save();
res.render("user-panel", {
user: req.user
});
}
}
});
});
You should try not to use authentication logic within each function, rather have it as a seperate function and import it as middleware. Makes it cleaner. I've rewritten it for you.
function authCheck(req, res, next) {
if(req.isAuthenticated()) {
next()
} else {
res.redirect('/login');
}
}
now within any new function you create (within this file), you can just use the function authCheck() as middleware:
app.get('/', authCheck, (req, res) => {

Cannot read property 'heading' of null

My problem is I got an unexpected error at the browser end that says Cannot read property 'heading' of null
also marks this error at the client page file like about.ejs and showing; in the snap attached
I have provided all the required codes related to this. I reviewed multiple times to find for what or to where the actual errror originated but did not able to fix it.
codes of about.ejs
<%-include('./partials/header')%>
<div class="container-fluid">
<h1>About Section</h1>
<div class="card shadow mb-4">
<div class="card-header">
<form action="/admin/portfolio/create" method="post">
<button type="submit" class="btn btn-success">Edit About Page</button>
</form>
</div>
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">About Area</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<form action="/admin/about" method="post" >
<div class="form-group">
<label for="exampleFormControlInput1">Headings:</label>
<input class="form-control" type="text" name="heading" id="exampleFormControlInput1" value="<%=about.heading%>" >
</div>
<div class="form-group">
<label for="exampleFormControlInput2">Sub-Headings:</label>
<input class="form-control" type="text" name="subheading" id="exampleFormControlInput2" value="<%=about.subheading%>" >
</div>
<div class="form-group">
<textarea id="editor1" name="content" rows="10" cols="80"><%=about.content%></textarea>
</div>
<button type="submit" class="btn btn-primary">Save & Update</button>
</form>
</div>
</div>
</div>
<%-include('./partials/footer')%>
here is my router.js file
router.get('/admin/about',serverController.isAuthenticated,serverController.about)
router.post('/admin/about',serverController.isAuthenticated,serverController.about_post)
This is also my controller file
exports.about = async function(req,res){
res.render('server/about', {
about : await aboutCollection.findOne()
})
}
exports.about_post = function(req,res){
let about = new About(req.body)
about.create().then(async()=>{
res.redirect('/admin/about')
}).catch(()=>{
res.send('404')
})
}
and finally this all about my model of about page
const aboutCollection = require('../db').db().collection('about')
const objectId = require('mongodb').ObjectID
const About = function(about){
this.about = about
}
About.prototype.create = function(){
return new Promise(async(resolve,reject)=>{
await aboutCollection.updateOne({}, {$set :
{
heading : this.about.heading,
subheading : this.about.subheading,
content : this.about.content
}
})
resolve()
})
}
module.exports = About
it's because about sent value of none at the ejs tag i mean
<%= about.heading%>
Do,
exports.about = async function(req,res){
res.render('server/about', {
about : await aboutCollection.find().toArray()
})
}
Instead of,
exports.about = async function(req,res){
res.render('server/about', {
about : await aboutCollection.findOne()
})
}
In my case, I did this; after trying then see error has gone.

Logic doesn't work after .then

I have a Login end point that respond me a json.
I'm using vue-router to do a POST and then Store a token in localStorage, but after the POST, the json shows on the screen:
{"success":false,"message":"Login ou senha inválidos!"}
It should return on the page login, with the message
This is the code:
var vmLogin = new Vue({
el: '#login',
data: {
email: '',
msg: '',
password: ''
},
beforeCreate: function () {
if(localStorage.getItem("timeTaskToken") !== null) {
window.location.href = '/'
}
},
methods: {
getLogin: function (e) {
this.$http.post('/login', {email: this.email, password: this.password}).then((response) => {
alert('teste!');
if(response.body.success === true) {
localStorage.setItem("timeTaskToken", response.body.token);
window.location.href = '/'
} else {
this.msg = response.body.message
}
}, (response) => {
// error callback
});
e.preventDefault();
}
}
});
login page
<form id="login" class="form-horizontal" method="post">
<h3>{{ msg }}</h3>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="email" v-model="email" class="form-control" name="email" placeholder="Email">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="password" v-model="password" class="form-control" name="password" placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox"> Remember me
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default" #click="getLogin">Sign
in</button>
</div>
</div>
</form>
It's like nothing after .then works...
The returned JSON just appear in the screen.
I expect the problem is that the Sign In button is a submit button and you just want it to be a button button.
Change
<button type="submit" class="btn btn-default" #click="getLogin">Sign in</button>
To
<button type="button" class="btn btn-default" #click="getLogin">Sign in</button>
Note the type="button".
If you leave it as type submit then the form is is actually posted and code execution will stop. This also explains why you see a page that has just the JSON result; that is just the response from posting that form.
Alternatively, move e.preventDefault() to the top of the method.
You could also use #click.prevent="getLogin".
Just add a console.error in you error callback
}, (response) => {
console.error(response);
});
This is the first step because maybe you just enter here ..

how to update a login name in header component from logincomponent in angularjs 4.0

Hi I need to update login name in a header after a user logs in.
this is my code:
app.componet.html
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
app.component.ts
import { Component,OnDestroy } from '#angular/core';
import { MyservicesService } from './myservices.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(private myservices: MyservicesService) {
}
}
Header.component.html
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<img class="img-responsive" src="assets/images/logo.png" alt="logo">
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav navbar-right">
<li><a routerLink="home" routerLinkActive="active">Home</a></li>
<li><a routerLink="shop">Shop</a></li>
<li>About us</li>
<li>Contact</li>
<li *ngIf="displayuser" class="dropdown">
<a class="dropdown-toggle displaycurrentuser" data-toggle="dropdown" href="#">{{currentusername}}
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a (click)="logOut()">Log out</a></li>
</ul>
</li>
<li *ngIf="!displayuser"><button style="margin-top: -10px;" class="btn btn-primary"> Login / Register</button></li>
<li><a routerLink="cartlist"><span><i class="fa fa-shopping-cart" aria-hidden="true"></i> {{noofitemsincart}} </span></a></li>
</ul>
</div>
</div>
</nav>
Header.component.ts
import { Component, OnInit,Input } from '#angular/core';
import { AuthenticationService } from '../authentication.service';
import { MyservicesService } from '../myservices.service';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
displayuser:boolean = false;
currentusername;
noofitemsincart;
user:any;
constructor(private authenticationService: AuthenticationService,private myservices: MyservicesService) {
}
ngOnInit() {
this.user = this.authenticationService.getCurrentUserData();
if(this.user!=null){
//this.user=JSON.parse(this.user);
if(this.user.UserNameorEmail!=null){
this.displayuser=true;
console.log("displayuser "+this.displayuser);
this.currentusername=this.user.UserNameorEmail;
}
}
}
logOut() {
this.user= this.authenticationService.logout();
this.displayuser=false;
}
}
Loginorregistercomponent.html
<section class="news_area newsblock">
<div class="container">
<div class="row">
<div class="section-title">
<h2>my <span>account</span></h2>
</div>
</div>
<!--endrow-->
<div class="row">
<div class="col-md-6 col-sm-6 col-xs-12 spaceblock">
<div class="login">
<h3 class="titlel">Login</h3>
</div>
<form name="form" (ngSubmit)="loginform.form.valid && login()" #loginform="ngForm" novalidate>
<div class="loginpart">
<div class="form-group froma" [ngClass]="{'has-error': loginform.submitted && !username.valid}">
<label for="email">Username or email address <span class="required"> *</span></label>
<input type="email" class="form-control" id="email" placeholder="" name="username" name="username" [(ngModel)]="model.username"
#username="ngModel" required>
<div *ngIf="loginform.submitted && !username.valid" class="help-block">Username is required</div>
</div>
<div class="form-group" [ngClass]="{ 'has-error': loginform.submitted && !password.valid }">
<label for="pwd">Password<span class="required"> *</span></label>
<input type="password" class="form-control" id="pwd" placeholder="" name="password" [(ngModel)]="model.password" #password="ngModel"
required>
<div *ngIf="loginform.submitted && !password.valid" class="help-block">Password is required</div>
</div>
<div class="checkbox">
<label><input type="checkbox" name="remember"> Remember me</label>
</div>
<button [disabled]="lloading" type="submit" class="btn btn-primary">Login</button>
<img *ngIf="lloading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="
/>
<div class="lostpass">Lost your password?</div>
<div *ngIf="lerror" class="danger">{{lerror}}</div>
</div>
</form>
</div>
<div class="col-md-6 col-sm-6 col-xs-12 spaceblock">
<div class="login">
<h3 class="titlel">Register</h3>
</div>
<form name="form" (ngSubmit)="registerform.form.valid && register()" #registerform="ngForm" novalidate>
<div class="loginpart">
<div class="form-group froma" [ngClass]="{ 'has-error': registerform.submitted && !newusername.valid }">
<label for="email">Email address <span class="required"> *</span></label>
<input type="email" class="form-control" id="email" placeholder="" name="newusername" [(ngModel)]="registermodel.newusername"
#newusername="ngModel" required>
<div *ngIf="registerform.submitted && !newusername.valid" class="help-block">Username is required</div>
</div>
<div class="form-group" [ngClass]="{ 'has-error': registerform.submitted && !newpassword.valid }">
<label for="pwd">Password<span class="required"> *</span></label>
<input type="password" class="form-control" id="pwd" placeholder="" name="newpassword" [(ngModel)]="registermodel.newpassword"
#newpassword="ngModel" required>
<div *ngIf="registerform.submitted && !newpassword.valid" class="help-block">Password is required</div>
</div>
<button type="submit" [disabled]="rloading" class="btn btn-primary">Register</button>
<img *ngIf="rloading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="
/>
<div *ngIf="rerror" class="danger">{{rerror}}</div>
</div>
</form>
</div>
</div>
<!--endimgSection-->
</div>
</section>
Loginorregistercomponent.ts
import { Component, OnInit } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { AuthenticationService } from '../authentication.service';
#Component({
selector: 'app-loginorregister',
templateUrl: './loginorregister.component.html',
styleUrls: ['./loginorregister.component.css']
})
export class LoginorregisterComponent implements OnInit {
model: any = {};
registermodel: any = {};
lloading = false;
rloading = false;
returnUrl: string;
lerror;
rerror;
constructor( private route: ActivatedRoute,
private router: Router,
private authenticationService: AuthenticationService) { }
ngOnInit() {
this.authenticationService.logout();
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
}
login() {
        this.lloading = true;
        this.authenticationService.login(this.model.username, this.model.password)
            .subscribe(
                data => {
console.log(data);
if(!data.hasOwnProperty('Code')){
this.router.navigate([this.returnUrl]);
}else{
this.lerror=data.Message;
console.log(this.lerror);
                    this.lloading = false;
}
                
                },
                error => {
                    //this.alertService.error(error);
this.lerror=error;
console.log(error);
                    this.lloading = false;
                });
    
    }
register() {
this.rloading = true;
this.authenticationService.create(this.registermodel.newusername, this.registermodel.newpassword)
.subscribe(
data => {
data=JSON.parse(data);
if(!data.hasOwnProperty("Code")){
this.router.navigate([this.returnUrl]);
console.log("in data "+data);
}
else{
console.log("out data "+data.Message);
this.rerror=data.Message;
this.rloading = false;
}
},
error => {
// this.alertService.error(error);
this.rerror=error;
this.rloading = false;
});
}
}
authenticationService.ts
import { Injectable } from '#angular/core';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map'
#Injectable()
export class AuthenticationService {
user:any;
headers = new Headers({ 'Content-Type': 'application/json' });
options = new RequestOptions({ headers: this.headers });
constructor(private http: Http) { }
login(username: string, password: string) {
return this.http.post('http://www.myweb.com/User/Login', JSON.stringify({UserNameorEmail: username,Password: password}),this.options)
.map((response: Response) => {
let user = response.json();
console.log("in service "+user);
if (user) {
localStorage.setItem('currentUser', JSON.stringify(user));
console.log("user.token "+user);
}
return user;
});
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
}
create(username: string, password: string) {
return this.http.post('http://www.myweb.com/User/Add', JSON.stringify({UserNameorEmail: username, Password: password }),this.options)
.map((response: Response) => {
let user = response.json();
if (user) {
localStorage.setItem('currentUser', JSON.stringify(user));
}
return user;
});
}
getCurrentUserData(){
this.user= localStorage.getItem("currentUser");
this.user=JSON.parse(this.user);
if(this.user!=null){
if(this.user.UserNameorEmail!=null){
return this.user;
}else{
return this.user=null;
}
}else{
return this.user=null;
}
}
}
I typically have a state.service.ts in my projects in which I store application state (current user etc.)
In this, I create the following:
// BehaviorSubject to store UserName
private currentUserNameStore = new BehaviorSubject<string>("");
// Make UserName store Observable
public currentUserName$ = this.currentUserNameStore.asObservable();
// Setter to update UserName
setCurrentUserName(userName: string) {
this.currentUserNameStore.next(userName);
}
Then in the header component where you need to display the current User, you subscribe to the Observable from your state service:
stateSvc.currentUserName$
.subscribe(
userName => {
userName = userName;
});
And you can display this in the header like this:
{{userName}}
Then in your login component, once you've got a logged in user, you set the value using the Setter in the service:
this.stateSvc.setCurrentUserName(this.userName);
As the Title on the header component is subscribed, it will pickup the changes and update the display on the component.
You have to check authenticity of user before loading <app-header> </app-header>
i.e.
<div *ngIf="authorised">
<app-header></app-header>
</div>
where authorised is a member of app.component.ts.
i.e. You have to make sure if displayuser or currentusername is available before rendering <app-header></app-header>.
Please mark if you find it helpful.

Ajax function not working properly for delete and update comments

I'm using Ajax in a comments section in my blog project. It was working fine however clearly I've changed something because now when I go to edit a comment it won't work and when I try to delete, it does destroy the comment but it also gets rid of a load of other comments until I refresh the page when everything looks fine. The only Ajax function now working is create new comment.
Here's my show page code for my comments section:
<!--================== COMMENTS DISPLAY SECTION ====================================================================-->
<div id="comments">
<% blog.comments.forEach(function(comment){ %>
<div class="comment-container">
<div class="jumbotron comment">
<div class="row">
<div class="col-md-1">
<img class="comment-ico" src = "<%=comment.author.image%>">
</div>
<div class="col-md-7">
<h4><%=comment.author.username%></h4>
</div>
</div>
</div>
<div><p><%=comment.text%></p></div>
<!--=================EDIT COMMENT FORM =========================================================================-->
<form id="edit-comment-form" action = "/blogs/<%= blog._id %>/comments/<%=comment._id%>?_method=PUT" method = "POST" id="newComment">
<textarea class = "form-control" rows="4" name = "comment[text]"><%=comment.text%></textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
<!--==================================================================================================================-->
<!-- if current user is the same as author -->
<% if(currentUser && currentUser.username == comment.author.username) { %>
<div class="row">
<div class="col-md-1 choice">
<a class="edit">Edit</a>
</div>
<div class="col-md-1">
<form id = "delete-form" action = "/blogs/<%= blog._id %>/comments/<%=comment._id%>?_method=DELETE" method = "POST">
<input type = "submit" class = "button-delete" value = "Delete"></form>
</div>
<% } %>
<% if(currentUser && currentUser.username == comment.author.username) { %>
<div class="col-md-1 choice-report">
<a class="report">Report</a>
</div>
<% } else { %>
<div class="col-md-1 choice-no-user">
Report
</div>
<% } %>
</div>
<br>
<hr class = "style-three">
<% }) %>
</div>
</div>
</div>
<!--==================================================================================================================-->
<% if(currentUser){ %>
<div class = "container-form">
<form action = "/blogs/<%= blog._id %>/comments" method = "POST" id="newComment">
<div class="row">
<div class="col-md-2">
<img class="newComment-ico" src = " <%=currentUser.image%>">
</div>
<div class="col-md-10">
<label for="comment">Add comment</label>
</div>
</div>
<textarea class = "form-control" rows="4" placeholder = "Type comment here..." name = "comment[text]"></textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
</div>
<% } %>
And my Ajax code:
// update comment
$('#comments').on('submit', '#edit-comment-form', function(e){
e.preventDefault();
// get info from form
var formData = $(this).serialize();
var formAction = $(this).attr('action');
var $originalItem = $(this).parent('.comment-container');
$.ajax({
url: formAction,
data: formData,
type: 'PUT',
originalItem: $originalItem,
success: function(data) {
var blog_id = location.pathname.replace("/blogs/", "");
this.originalItem.html(
`
<div class="comment-container">
<div class="jumbotron comment">
<div class="row">
<div class="col-md-1">
<img class="comment-ico" src = "${data.author.image}">
</div>
<div class="col-md-7">
<h4>${data.author.username}</h4>
</div>
</div>
</div>
<div><p>${data.text}</p></div>
<form id="edit-comment-form" action = "/blogs/${blog._id}/comments/${data._id}?_method=PUT" method = "POST" id="newComment">
<textarea class = "form-control" rows="4" name = "comment[text]">${data.text}</textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
<div class="row">
<div class="col-md-1 choice">
<a class="edit">Edit</a>
</div>
<div class="col-md-1">
<form id = "delete-form" action = "/blogs/${blog._id}/comments/${data._id}?_method=DELETE" method = "POST">
<input type = "submit" class = "button-delete" value = "Delete"></form>
</div>
<div class="col-md-1 choice-report">
<a class="report">Report</a>
</div>
</div>
<br>
<hr class = "style-three">
`
);
}
});
});
And here's the update comments route:
// comment update route
router.put("/:comment_id", function(req, res){
Comment.findByIdAndUpdate(req.params.comment_id, req.body.comment, {new: true}, function(err, updatedComment){
if(err) {
res.redirect("back");
} else {
if(req.xhr);
res.json(updatedComment);
// } else {
// res.redirect("/blogs/" + req.params.id);
// }
}
})
})
My destroy Ajax code:
// delete comments asynchonously
$('#comments').on('submit', '#delete-form', function(e){
e.preventDefault();
var confirmResponse = confirm('Are you sure you want to delete this comment?');
if(confirmResponse){
var actionURL = $(this).attr('action');
$itemToDelete = $(this).closest('.comment-container');
$.ajax({
url: actionURL,
type: 'DELETE',
itemToDelete: $itemToDelete,
success: function(data){
this.itemToDelete.remove();
}
})
} else {
$(this).find('input').blur();
}
})
And destroy route:
// comments destroy route
router.delete("/:comment_id", function(req, res){
Comment.findByIdAndRemove(req.params.comment_id, function(err, comment){
if(err) {
res.redirect("back");
} else {
res.json(comment);
}
})
})
UPDATE:
I noticed a couple of errors on my Ajax code whereby I had referenced ${blog._id} rather than ${blog_id}. I've updated as follows:
// update comment
$('#comments').on('submit', '#edit-comment-form', function(e){
e.preventDefault();
// get info from form
var formData = $(this).serialize();
var formAction = $(this).attr('action');
var $originalItem = $(this).parent('.comment-container');
$.ajax({
url: formAction,
data: formData,
type: 'PUT',
originalItem: $originalItem,
success: function(data) {
var blog_id = location.pathname.replace("/blogs/", "");
this.originalItem.html(
`
<div class="jumbotron comment">
<div class="row">
<div class="col-md-1">
<img class="comment-ico" src = "${data.author.image}">
</div>
<div class="col-md-7">
<h4>${data.author.username}</h4>
</div>
</div>
</div>
<div><p>${data.text}</p></div>
<form id="edit-comment-form" action = "/blogs/${blog_id}/comments/${data._id} method = "POST" id="newComment">
<textarea class = "form-control" rows="4" name = "comment[text]">${data.text}</textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
<div class="row">
<div class="col-md-1 choice">
<a class="edit">Edit</a>
</div>
<div class="col-md-1">
<form id = "delete-form" action = "/blogs/${blog_id}/comments/${data._id}?_method=DELETE" method = "POST">
<input type = "submit" class = "button-delete" value = "Delete"></form>
</div>
<div class="col-md-1 choice-report">
<a class="report">Report</a>
</div>
</div>
<br>
<hr class = "style-three">
`
);
}
});
});
Now the comment will update asynchronously, however until the page is refreshed, again it's kicking off a load of other comments.Essentially it's getting rid temporarily of all comments beneath the one being edited. When you refresh though, all comments re-appear in the correct order including the edits made to the comment in question

Resources