Am getting this error when google auth redirects to my secrets page. And also in the secrets page I can't post secrets as they aren't posted in my database. I don't know which elements I have called wrongly.
<%- include('partials/header') %>
<div class="jumbotron text-center">
<div class="container">
<i class="fas fa-key fa-6x"></i>
<h1 class="display-3">You've Discovered My Secret!</h1>
<% usersWithSecrets.forEach(function(foundUsers){ %>
<p class="secret-text"><%=foundUsers.secret%></p>
<% }) %>
<hr>
<a class="btn btn-light btn-lg" href="/logout" role="button">Log Out</a>
<a class="btn btn-dark btn-lg" href="/submit" role="button">Submit a Secret</a>
</div>
</div>
<%- include('partials/footer') %>
app.get("/secrets", function(req,res){
if (req.isAuthenticated()) {
User.find({"secret": {$ne: null}}, function(err, foundUsers){
if(foundUsers){
res.render("secrets", {usersWithSecrets: foundUsers});
}else {
console.log(err);
}
});
app.post("/submit", function(req, res){
const submittedSecret = req.body.secret;
User.findById(req.user.id, function(err, foundUser){
if (err) {
console.log(err);
}else{
if (foundUser) {
foundUser.secret=submittedSecret;
submittedSecret.save(function(){
res.redirect("/secrets");
});
}
}
});
});
The first block of code should catch the user and redirect them to the app.get(secrets)
The second block is a user can post a secret and caught in the database but the page keeps loading infinitely.
Related
I'm trying to upload (update acutally) an image to a db and then redirect to profile page, i tried everything and the photo is updated successfully in the db but page wont redirect.
If i dont attach an image everything is ok and user gets redirected.
If i do attach an image user just stays on form page, no errors pop up, page just gets refreshed (photo gets updated in db successfully)
post route
var store = require("./multer");
router.post("/:username/edit", isUser, personalContent, store.single("profilePic"), async (req, res) => {
try {
if (req.file) {
await User.updateOne(
{ username: req.user.username },
{
username: req.params.username,
dateOfBirth: req.body.date,
filename: req.file.originalname,
contentType: req.file.mimetype,
imageBase64: fs.readFileSync(req.file.path).toString("base64"),
},
{ upsert: true }
);
} else {
await User.updateOne(
{ username: req.user.username },
{
username: req.params.username,
dateOfBirth: req.body.date,
},
{ upsert: true }
);
}
res.redirect("/profile/" + req.params.username + "?msg=Profile updated successfully");
} catch (err) {
console.log(err);
res.redirect("/profile/" + req.params.username + "?msg=Error while updating profile");
}
});
ejs form
<form action="/profile/<%= user.username %>/edit" enctype="multipart/form-data" method="POST">
<% if(error){ %> <%= error %> <% } %> <% if(msg){ %> <%= msg %> <% } %>
<div>
<label for="username">Username: </label>
<input type="text" name="username" value="<%= user.username %>" disabled />
</div>
<div>
<label for="date">Date of birth: </label>
<input type="date" name="date" required value="<%= user.dateOfBirth.toISOString().split("T")[0] %>" />
</div>
<div>
<label for="profpic">Profile picture:</label>
<input type="file" name="profilePic" />
<div>
<% if(user.imageBase64){ %>
<img src="data:<%=user.contentType%>;base64,<%=user.imageBase64%>" alt="" style="height: 3rem" />
<% }else{ %> Add profile picture <% } %>
</div>
</div>
<button type="submit">Submit</button>
</form>
multer.js
const multer = require("multer");
//set storage
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "uploads");
},
filename: (req, file, cb) => {
cb(null, file.fieldname + "-" + Date.now());
},
});
module.exports = store = multer({ storage: storage });
The issue was with LiveServer chrome extension, it was messing something up with redirects. Now this question seems stupid to me but if someone stumbled upon this I hope I could help
My Nested {{#each}} does not work.
I am Scraping article titles to my page and I'm using MongoDB/Mongoose. For each article (that I named News) I want user to post comments and view previous comments.
My routes, console.log, and the database itself shows that my api routes are working, but I can't get the comments to display.
My handlebars has the articles rendering to screen, but when GETting the comments it returns a 304.
The Articles display as I intend, it only has a problem with the comments
{{#each News}} is each article
{{#each comment}} is nested inside each News.
{{#each News}}
<div class="panel-block is-active">
<ul>
<li>
<div class="level-left">
<h2 class="subtitle">
<a href="https://www.atptour.com{{this.url}}">
{{this.headline}}
</a>
</h2>
</div>
</li>
<li>
<img width="348" src="https://www.atptour.com{{this.thumbNail}}">
</li>
<li>
<p>{{category}}</p>
</li>
<li>
{{!-- on click remove class .is-hidden on #getComments --}}
<p id="showComments" data-id="{{this._id}}" >Comments</p>
</li>
<li>
{{#each comment}}
<article id="getComments" class="media is-hidden">
<div class="media-content">
<div class="content">
<p>
<small>{{this.time}}</small>
<br />
{{this.body}}
</p>
</div>
</div>
<div class="media-right">
<button class="delete"></button>
</div>
</article>
{{/each}}
{{!-- on click remove class .is-hidden on #postComments --}}
<a id="addComment" >Add Comment</a>
{{!-- TO POST A COMMENT --}}
<article id="postComment" class="media is-hidden">
<div class="media-content">
<div class="field">
<p class="control">
<textarea
class="textarea"
placeholder="Add a comment..."
></textarea>
</p>
</div>
<div class="level">
<div class="level-left">
<div class="level-item">
<a class="button is-info">Submit</a>
</div>
</div>
</div>
</div>
</article>
</li>
</ul>
</div>
{{/each}}
In the {{#each comment}} {{this.time}} and {{this.body}} is blank. But if I simply put {{this}} I get the _id if each comment. The context must be wrong but I don't know why. The comments are properly associated to the News because I can check the get route and it's all there correctly.
Here are the schemas if it helps
new articles
const NewsSchema = new Schema({
headline: {
type: String,
required: true,
},
thumbNail: {
type: String,
required: true,
},
category: {
type: String,
required: true,
},
url: {
type: String,
required: true,
},
// Comments will populate the News
comment: [
{
type: Schema.Types.ObjectId,
ref: "Comment",
},
],
});
const News = mongoose.model("News", NewsSchema);
comments
const CommentSchema = new Schema({
time: {
type: Date,
default: Date.now,
required: true,
},
body: {
type: String,
required: true,
},
});
const Comment = mongoose.model("Comment", CommentSchema);
It wasn't a handlebars problem at all!
It was a route problem.
I was doing this:
app.get("/", function(req, res) {
db.News.find()
.then(News => {
res.render("index", { News });
})
.catch(err => {
console.log(err);
});
});
When I should have been doing this
app.get("/", function(req, res) {
db.News.find()
.populate("comment")
.then(News => {
res.render("index", { News });
})
.catch(err => {
console.log(err);
});
});
I forgot to populate in the res.render. (I was populating the api route, but not this 1!)
I am having the following problem in my project. I am trying to delete an added product but unfortunately, it cannot be deleted. So let me show you my code.
First I have the Product.js model.
static deleteById(prodId){
const db = getDb();
return db
.collection('products')
.deleteOne({_id: new mongodb.ObjectId(prodId) })
.then(result => {
console.log('Deleted');
})
.catch(err => {
console.log(err);
});
}
Then I use deleteById function in my controller Admin.js file.
exports.postDeleteProduct = (req, res, next) => {
const prodId = req.params.productId;
Product.deleteById(prodId)
.then(() => {
console.log('DESTROYED PRODUCT');
res.redirect('/admin/products');
})
.catch(err => console.log(err));
};
After doing that I am creating the necessary route in the routes->admin.js file.
const path = require('path');
const express = require('express');
const adminController = require('../controllers/admin');
const router = express.Router();
// /admin/add-product => GET
router.get('/add-product', adminController.getAddProduct);
// admin/products => GET
router.get('/products', adminController.getProducts);
// /admin/add-product => POST
router.post('/add-product', adminController.postAddProduct);
router.get('/edit-product/:productId', adminController.getEditProduct);
router.post('/edit-product', adminController.postEditProduct);
router.post('/delete-product', adminController.postDeleteProduct);
module.exports = router;
Finally, there is the HTML file which contains the delete button.
<main>
<% if (prods.length > 0) { %>
<div class="grid">
<% for (let product of prods) { %>
<article class="card product-item">
<header class="card__header">
<h1 class="product__title">
<%= product.title %>
</h1>
</header>
<div class="card__image">
<img src="<%= product.imageUrl %>" alt="<%= product.title %>">
</div>
<div class="card__content">
<h2 class="product__price">$
<%= product.price %>
</h2>
<p class="product__description">
<%= product.description %>
</p>
</div>
<div class="card__actions">
Edit
<form action="/admin/delete-product" method="POST">
<input type="hidden" value="<%= product._id %>" name="productId">
<button class="btn" type="submit">Delete</button>
</form>
</div>
</article>
<% } %>
</div>
<% } else { %>
<h1>No Products Found!</h1>
<% } %>
</main>
<%- include('../includes/end.ejs') %>
Here is my repo.
How can the delete problem be fixed?
Hi i found a sample of auth on routing with angularfire, i just change it to support the new firebase sdk v4 and still using angularfire v1.
this is the link of the piece of code i used (with ui-router) :
angularfire docs
now this is my app.js and index.html
var config = {
"apiKey": "AIzaSyAUoM0RYqF1-wHI_kYV_8LKgIwxmBEweZ8",
"authDomain": "clubears-156821.firebaseapp.com",
"databaseURL": "https://clubears-156821.firebaseio.com",
"projectId": "clubears-156821",
"storageBucket": "clubears-156821.appspot.com",
"messagingSenderId": "970903539685"
};
firebase.initializeApp(config);
var app = angular.module("sampleApp", [
"firebase",
"ui.router"
]);
app.factory("Auth", ["$firebaseAuth",
function ($firebaseAuth) {
return $firebaseAuth();
}
]);
// UI.ROUTER STUFF
app.run(["$rootScope", "$state", function ($rootScope, $state) {
$rootScope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) {
if (error === "AUTH_REQUIRED") {
$state.go("home");
}
});
}]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state('home', {
url: "/home",
template: "<h1>Home</h1><p>This is the Home page</p>",
resolve: {
"currentAuth": ["Auth", function (Auth) {
return Auth.$waitForAuth();
}]
}
})
.state('profile', {
url: "/profile",
template: "<h1>Profile</h1><p>This is the Profile page</p>",
resolve: {
"currentAuth": ["Auth", function (Auth) {
return Auth.$requireSignIn();
}]
}
})
});
app.controller("MainCtrl", ["$scope", "Auth",
function ($scope, Auth) {
$scope.auth = Auth;
console.log(Auth);
$scope.auth.$onAuth(function(authData) {
$scope.authData = authData;
console.log(authData);
});
}
]);
app.controller("NavCtrl", ["$scope", "Auth",
function ($scope, Auth) {
$scope.auth = Auth;
console.log(Auth);
$scope.auth.$onAuth(function(authData) {
$scope.authData = authData;
});
}
]);
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
</head>
<body>
<div ng-app="sampleApp">
<div ng-controller="MainCtrl">
<nav class="navbar navbar-default navbar-static-top" ng-controller="NavCtrl">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="home">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li ui-sref-active="active">
<a ui-sref="home" href="#">Home</a>
</li>
<li ui-sref-active="active" ng-show="authData">
<a ui-sref="profile" href="#">
My Profile
</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-hide="authData">
<a href="#" ng-click="$parent.auth.$authWithOAuthPopup('facebook')">
<span class="fa fa-facebook-official"></span>
Sign In with Facebook
</a>
</li>
<li ng-show="authData">
<a href="#" ng-click="$parent.auth.$unauth()">
<span class="fa fa-sign-out"></span>
Logout
</a>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div ui-view ng-show="authData"></div>
<div class="login-screen" ng-hide="authData">
<div class="jumbotron text-center">
<h1>Sweet login, brah.</h1>
<p class="lead">This is a pretty simple login utilizing AngularJS and AngularFire.</p>
<button class="btn btn-primary btn-lg" ng-click="auth.$authWithOAuthPopup('facebook')">
<span class="fa fa-facebook-official fa-fw"></span>
Sign in with Facebook
</button>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.0.0/firebase.js"></script>
<script src="app.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/1.1.3/angularfire.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.min.js"></script>
</body>
</html>
now the problem is that i getting an error : Cannot read property 'onAuth' of undefined.
i think its problem of the version of the new SDk and i looked in the proposed solution here in stackoverflow but none of them fix me the problem.
please help...
Ok i figure out the problem and fix it by changing the versions of angular and angularfire. and a little change to migrate to the new sdk.
this is new code.
my problem now is that i don't get all the scope that i want from facebook. for example i want birthday and i cannot see it comes back.
someone have a suggestion ?
var config = {
"apiKey": "AIzaSyAUoM0RYqF1-wHI_kYV_8LKgIwxmBEweZ8",
"authDomain": "clubears-156821.firebaseapp.com",
"databaseURL": "https://clubears-156821.firebaseio.com",
"projectId": "clubears-156821",
"storageBucket": "clubears-156821.appspot.com",
"messagingSenderId": "970903539685"
};
firebase.initializeApp(config);
var app = angular.module("sampleApp", [
"firebase",
"ui.router"
]);
app.factory("Auth", ["$firebaseAuth",
function ($firebaseAuth) {
return $firebaseAuth();
}
]);
//var provider = Auth.FacebookAuthProvider();
//provider.addScope('user_birthday');
//
//Auth.signInWithRedirect(provider);
// UI.ROUTER STUFF
app.run(["$rootScope", "$state", function ($rootScope, $state) {
$rootScope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) {
if (error === "AUTH_REQUIRED") {
$state.go("home");
}
});
}]);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state('home', {
url: "/home",
template: "<h1>Home</h1><p>This is the Home page</p>",
resolve: {
"currentAuth": ["Auth", function (Auth) {
return Auth.$waitForSignIn();
}]
}
})
.state('profile', {
url: "/profile",
template: "<h1>Profile</h1><p>This is the Profile page</p>",
resolve: {
"currentAuth": ["Auth", function (Auth) {
return Auth.$requireSignIn();
}]
}
});
});
app.controller("MainCtrl", ["$scope", "Auth",
function ($scope, Auth) {
$scope.auth = Auth;
console.log(Auth);
$scope.auth.$onAuthStateChanged(function (authData) {
$scope.authData = authData;
console.log(authData);
});
}
]);
app.controller("NavCtrl", ["$scope", "Auth",
function ($scope, Auth) {
$scope.currentUser = null;
$scope.currentUserRef = null;
$scope.currentLocation = null;
$scope.auth = Auth;
console.log(Auth);
/**
* Function called when clicking the Login/Logout button.
*/
// [START buttoncallback]
$scope.SignIn = function () {
if (!Auth.currentUser) {
$scope.auth.$signInWithRedirect('facebook', {
scope: 'email, public_profile, user_birthday'
}).then(function (authData) {
// never come here handle in $onAuthStateChanged because using redirect method
}).catch(function (error) {
if (error.code === 'TRANSPORT_UNAVAILABLE') {
$scope.$signInWithPopup('facebook', {
scope: 'email, public_profile, user_friends'
}).catch(function (error) {
console.error('login error: ', error);
});
} else {
console.error('login error: ', error);
}
});
} else {
// [START signout]
Auth.signOut();
// [END signout]
}
};
// [END buttoncallback]
//
// $scope.updateUserData = function () {
// $scope.currentUserRef.set($scope.currentUser);
// };
$scope.auth.$onAuthStateChanged(function (authData) {
$scope.authData = authData;
console.log('after login');
console.log($scope.authData);
});
}
]);
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>
<div ng-app="sampleApp">
<div ng-controller="MainCtrl">
<nav class="navbar navbar-default navbar-static-top" ng-controller="NavCtrl">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="home">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li ui-sref-active="active">
<a ui-sref="home" href="#">Home</a>
</li>
<li ui-sref-active="active" ng-show="authData">
<a ui-sref="profile" href="#">
My Profile
</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-hide="authData">
<a href="#" ng-click="SignIn()">
<span class="fa fa-facebook-official"></span>
Sign In with Facebook
</a>
</li>
<li ng-show="authData">
<a href="#" ng-click="SignIn()">
<span class="fa fa-sign-out"></span>
Logout
</a>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div ui-view ng-show="authData"></div>
<div class="login-screen" ng-hide="authData">
<div class="jumbotron text-center">
<h1>Sweet login, brah.</h1>
<p class="lead">This is a pretty simple login utilizing AngularJS and AngularFire.</p>
<button class="btn btn-primary btn-lg" ng-click="SignIn()">
<span class="fa fa-facebook-official fa-fw"></span>
Sign in with Facebook
</button>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.0.0/firebase.js"></script>
<script src="app.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/2.3.0/angularfire.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.3/angular-ui-router.min.js"></script>
</body>
</html>
I am using mizzao/meteor-autocomplete and am having problems in trying to get it to work.
When viewing the page in my browser, I am getting no results at all when typing any text. I've created the appropriate collection:
Institutions = new Mongo.Collection("institutions");
and know that there is data in the actual db, however still no success.
I've included my files below.
publications.js (located in the server folder)
Meteor.publish('institutions', function(args) {
return Institutions.find({}, args);
});
registrationStart.js
I've two helpers; one that actually powers the search and the other that should be returning the institutions. I have also tried this with the token: '#' argument with no success.
if (Meteor.isClient) {
Template.registrationStart.helpers({
settings: function() {
return {
position: "top",
limit: 7,
rules: [{
collection: Institutions,
field: "name",
options: '',
matchAll: true,
template: Template.institutionSelectDisplay
}]
};
},
institutions: function() {
return Instititions.find();
}
});
Template.registrationStart.events({
"autocompleteselect input": function(event, template, doc) {
// Session.set(event.target.name, event.target.value);
console.log("selected: ", doc);
console.log("event.target.name: ", event.target.name);
console.log("event.target.value: ", event.target.value);
}
});
}
registrationStart.html template
<template name="registrationStart">
<div class="panel-body" id="loginForm">
<h2 class="pageTitle">veClient Registration</h2>
<form>
<div> </div>
<fieldset>
{{> inputAutocomplete settings=settings id="institution" class="input-xlarge" placeholder="type institution here"}}
</fieldset>
<div> </div>
<button type="submit" class="btn btn-primary btn-sm">Continue Registration</button>
</form>
</div>
</template>
And the template to be rendered
<template name="institutionSelectDisplay">
<p class="inst-state">{{city}}, {{state}}</p>
<p class="inst-name">{{name}}</p>
<p class="inst-description">{{email}}</p>
</template>
Problem resulted because there was no subscription to the "institutions" publication. So need to add a subscribe statement to the registrationStart.js file:
Meteor.subscribe('institutions');