How to combine Meteor.publish/Subscirbe and collection.allow? - meteor

I tried to write some code for understanding Meteor.publish/subscribe and collection.allow
Now It's don't have any error However I can't insert data to my collection.
testing.html
<head>
<title>testing</title>
</head>
<body>
<div class="container">
<div class="col-xs-2">
{{> loginButtons}}
</div>
<div class="col-xs-10">
{{> gettingContent}}
</div>
</div>
</body>
<template name="gettingContent">
<h1>These are all my contents.</h1>
{{#each gettingAll}}
{{title}}
{{author}}
{{/each}}
{{#if currentUser}}
<h2 class="alert">{{denie}}</h2>
<p>Title: <input type="text" id="title"/></p>
<p>Author: <input type="text" id="author"/></p>
<p><input type="button" value="Click" id="action" /></p>
{{/if}}
</template>
model.js
Content = new Meteor.Collection("Content");
Meteor.methods({
creatingContent: function(options) {
check(options, {
title: String,
author: String,
date: new Date()
});
Content.insert({
title: options.title,
author: options.author,
date: options.date
});
}
});
Content.allow({
insert: function(userId) {
if(Meteor.userId() === true){
return true;
} else {
return false;
}
}
});
clientTesting.js
Template.gettingContent.helpers({
gettingAll : function(){
return Meteor.subscribe("getAll");
}
});
var options = {
title: $("#title").val(),
author: $("#author").val(),
date: new Date()
};
Template.gettingContent.events({
'click #action' : function(event,options) {
event.preventDefault();
if(Meteor.userId() === true) {
Meteor.call("creatingContent",options);
console.log("Content was created.");
$("#title").val("");
$("#author").val("");
}else{
Session.set("deny", "You must be login for creating content.");
}
}
});
serverTesting.js
Meteor.publish('getAll', function(){
if(Content.find().count() === 0){
return Session.set("noData", "Data not found'");
} else {
return Content.find({},{sort:{'date':-1}});
}
});

I believe your problem is here: Meteor.userId() === true
By default, a Meteor userId is an alphanumeric character string. Testing for equality to true is always going to be false if the userId exists.
Try this:
if (Meteor.userId()) {
return true;
} else {
return false;
}
Or even simpler:
return !!Meteor.userId();

i didnt test this code but date: new Date() line is incorrect. It Should be Date.
check(options, {
title: String,
author: String,
date: Date
});

Okay Everyone I have fixed some code problem and just two thing I don't understand 1.How to use Meteor.subscribe with Template? and 2. How to render for showing my data. I got error like this
Exception from Deps recompute function: Error: {{#each}} currently only accepts arrays, cursors or falsey values.
testing.html
<head>
<title>testing</title>
</head>
<body>
<div class="container">
<div class="col-xs-2">
{{> loginButtons}}
</div>
<div class="col-xs-10">
{{> gettingContent}}
</div>
</div>
</body>
<template name="gettingContent">
<h1>These are all my contents.</h1>
{{#each gettingAll}}
<p>Title: {{title}}, Author: {{author}}</p>
{{/each}}
<h2 class="alert">{{denies}}</h2>
{{#if currentUser}}
<p>Title: <input type="text" id="title"/></p>
<p>Author: <input type="text" id="author"/></p>
<p><input type="button" value="Click" id="action" /></p>
{{/if}}
</template>
clientTesting
Template.gettingContent.helpers({
gettingAll : function(){
return Meteor.subscribe('getAll') && Content.find().count() ;
},
denies: function(){
return Session.get("deny");
}
});
var options1 = function(title, author){
var title = $("#title").val();
var author = $("#author").val();
if(_.isString(title) && !_.isEmpty(title) && _.isString(author) && !_.isEmpty(author) ){
var result = {title: title, author: author};
return result;
}else{
console.log("Invalid Data")
}
};
Template.gettingContent.events({
'click #action' : function(event) {
event.preventDefault();
Session.set("options", options1());
var options = Session.get("options");
if(Meteor.userId() && !_.isEmpty(options)) {
Meteor.call('creatingContent',options, function(){
console.log("Content was created.");
});
$("#title").val("");
$("#author").val("");
return Session.set("deny", "Your Data was created.");
}else {
return Session.set("deny", "Invalid Data.");
}
}
});
model.js
Content = new Meteor.Collection("Content");
Meteor.methods({
creatingContent: function(options) {
check(options, {
title: String,
author: String
});
if(options.title.length === 0)
throw new Meteor.Error(413, "noData Passed");
if(options.author.length === 0)
throw new Meteor.Error(413, "noData Passed");
Content.insert({
title: options.title,
author: options.author,
date: new Date().getTime()
});
}
});
Content.allow({
insert: function(userId) {
if(Meteor.userId() === true){
return true;
} else {
return false;
}
}
});
serverTesting.js
Meteor.publish('getAll', function(){
return Content.find({},{sort:{'date':-1}});
});

Related

"Match error: Expected string, got undefined" Recover Password

Template.ResetPwd.events({
'submit #forgot-password': function(event, template) {
event.preventDefault();
var forgotPasswordForm = $(event.currentTarget),
email = forgotPasswordForm.find('#forgotPasswordEmail').val().toLowerCase();
if (email !== "") {
Accounts.forgotPassword({
email: email
}, function(err) {
if (err) {
if (err.message === 'User not found [403]') {
console.log('This email does not exist.');
FlashMessages.sendSuccess(err.message, {
autoHide: true,
hideDelay: 8000
});
} else {
console.log('We are sorry but something went wrong.');
FlashMessages.sendSuccess('We are sorry but something went wrong', {
autoHide: true,
hideDelay: 8000
});
}
} else {
console.log('Email Sent. Check your mailbox.');
FlashMessages.sendSuccess('Email Sent', {
autoHide: true,
hideDelay: 4000
});
}
});
} else {
template.find('#form-messages').html('Email Invalido');
}
return false;
}
});
if (Accounts._resetPasswordToken) {
Session.set('resetPassword', Accounts._resetPasswordToken);
};
Template.setNewPass.helpers({
resetPassword: function() {
return Session.get('resetPassword');
}
});
Template.setNewPass.events({
'submit #set-new-password': function(e, template) {
e.preventDefault();
// var target = event.target;
// var password = target.resetpass.value;
// var passwordConfirm = target.verificy.value;
var resetPasswordForm = $(e.currentTarget),
password = resetPasswordForm.find('#resetPasswordPassword').val(),
passwordConfirm = resetPasswordForm.find('#resetPasswordPasswordConfirm').val();
// if (isNotEmpty(password) && areValidPasswords(password, passwordConfirm)) {
if (password === passwordConfirm) {
Accounts.resetPassword(Session.get('resetPassword'), password, function(err) {
if (err) {
console.log('We are sorry but something went wrong.');
FlashMessages.sendSuccess(err, {
autoHide: true,
hideDelay: 8000
});
} else {
console.log('Your password has been changed. Welcome back!');
FlashMessages.sendSuccess('Your password has been changed. Welcome back', {
autoHide: true,
hideDelay: 8000
});
Session.set('resetPassword', null);
}
});
} else {
FlashMessages.sendSuccess('contraseñas no son iguales', {
autoHide: true,
hideDelay: 8000
});
}
return false;
}
});
<template name="ResetPwd">
<div class="container">
<p>
{{> flashMessages}}
</p>
<form id="forgot-password">
<div class="col-xs-12">
<input class="inputStyle" type="text" id="forgotPasswordEmail" name="email" placeholder="Email">
</div>
<div class="col-xs-12">
<input class="btn-main" type="submit" value="Recuperar Contraseña">
</div>
<p id="form-messages"></p>
</form>
</div>
</template>
<template name="setNewPass">
<div class="container">
<p>
{{> flashMessages}}
</p>
<div class="row">
<form id="set-new-password">
<div class="col-xs-12">
<input class="inputStyle" type="password" name="resetpass" id="resetPasswordPassword" placeholder="contraseña">
<input class="inputStyle" type="password" name="verificy" id="resetPasswordPasswordConfirm" placeholder="verificar contraseña">
</div>
<div class="col-xs-12">
<input class="btn-main" type="submit" name="some_name" value="Recuperar Contraseña">
</div>
<p id="form-messages"></p>
</form>
</div>
</div>
</template>
Hello, I'm having trouble retrieving the password when sending the email with the token to retrieve it I receive it successfully then I press that url
http://localhost:1999/reset/_M5swGv9Uwn--4_olB0itOuYBLGMYYgDMQB9es9Y0TM
And it directs me to the window to change the password and I enter the new password there is where I get the following error errorClass
errorType : "Match.Error" message : "Match error: Expected string, got
undefined" path : "" sanitizedError : errorClass
In my code I have the following.

Meteor: How can I restrict user on a chat?

Im working on a project and my last task is to implement publish and subscribe to prevent users seeing conversations they were not involved in. We were given an example code and I notice a filter on the router.
Router.route('/chat/:_id', function () {
// the user they want to chat to has id equal to
// the id sent in after /chat/...
var otherUserId = this.params._id;
// find a chat that has two users that match current user id
// and the requested user id
var filter = {$or:[
{user1Id:Meteor.userId(), user2Id:otherUserId},
{user2Id:Meteor.userId(), user1Id:otherUserId}
]};
var chat = Chats.findOne(filter);
if (!chat){// no chat matching the filter - need to insert a new one
chatId = Chats.insert({user1Id:Meteor.userId(), user2Id:otherUserId});
}
else {// there is a chat going already - use that.
chatId = chat._id;
}
if (chatId){// looking good, save the id to the session
Session.set("chatId",chatId);
}
this.render("navbar", {to:"header"});
this.render("chat_page", {to:"main"});
});
I thought the filter should be on publish and then subscribe. Here is what I have now.
My HTML
<template name="chat_page">
<h2>Type in the box below to send a message!</h2>
<div class="row">
<div class="col-md-12">
<div class="well well-lg">
{{#each recentMessages}}
{{> message}}
{{/each}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
{{#if currentUser}}
<form class="new-message">
<input class="input" type="text" name="text" placeholder="type a message here...">
<button class="btn btn-default">Send</button>
</form>
{{/if}}
</div>
</div>
</template>
<!-- simple template that displays a message -->
<template name="message">
<div class = "container">
<div class = "row">
<div class = "username">
<img src="/{{avatar}}" class="avatar_img" >
{{username}}
said: {{messageText}}
</div>
</div>
</div>
</template>
Server Side
Meteor.startup(function () {
if (!Meteor.users.findOne()){
for (var i=1;i<9;i++){
var email = "user"+i+"#test.com";
var username = "user"+i;
var avatar = "ava"+i+".png"
console.log("creating a user with password 'test123' and username/ email: "
+ email);
Meteor.users.insert({
profile:{username:username, avatar:avatar},
emails: [{address:email}],
services:{
password:{"bcrypt" : "PASSWORD REMOVED"}}});
}
}
});
Meteor.publish("messages", function (userId) {
return Messages.find();
});
Meteor.publish("userStatus", function() {
return Meteor.users.find({ "status.online": true });
});
Meteor.publish("userData", function(){
if(this.userId) {
return Meteor.users.find({_id: this.userId},{
fields: {'other':1, 'things': 1}});
} else {
this.ready();
}
return Meteor.users.find({ "status.online": true })
});
Client Side
Meteor.subscribe("messages");
Meteor.subscribe("userStatus");
Meteor.subscribe("userData");
// set up the main template the the router will use to build pages
Router.configure({
layoutTemplate: 'ApplicationLayout'
});
// specify the top level route, the page users see when they arrive at the site
Router.route('/', function () {
console.log("rendering root /");
this.render("navbar", {to:"header"});
this.render("lobby_page", {to:"main"});
});
Router.route('/chat/:_id', function () {
this.render("navbar", {to:"header"});
this.render("chat_page", {to:"main"});
});
///
// helper functions
///
Template.message.helpers({
userName: function() {
var userId = this.userId;
var user = Meteor.users.findOne(userId);
var username = user && user.profile && user.profile.username;
var avatar = user && user.profile && user.profile.avatar;
return {
username: username,
avatar: avatar
}
}
})
Template.available_user_list.helpers({
users:function(){
return Meteor.users.find();
}
})
Template.available_user.helpers({
getUsername:function(userId){
user = Meteor.users.findOne({_id:userId});
return user.profile.username;
},
isMyUser:function(userId){
if (userId == Meteor.userId()){
return true;
}
else {
return false;
}
}
})
Template.chat_page.helpers({
recentMessages: function () {
if (Session.get("hideCompleted")) {
return Messages.find({checked: {$ne: true}}, {sort: {createdAt: -1}});
} else {
return Messages.find({}, {sort: {createdAt: 1}});
}
},
hideCompleted: function () {
return Session.get("hideCompleted");
},
incompleteCount: function () {
return Tasks.find({checked: {$ne: true}}).count();
}
});
Template.chat_page.events({
// this event fires when the user sends a message on the chat page
'submit .new-message':function(event){
console.log(event);
event.preventDefault();
var text = event.target.text.value;
// stop the form from triggering a page reload
event.target.text.value = "";
// see if we can find a chat object in the database
// to which we'll add the message
Meteor.call("sendMessage", text);
},
});
Collections
Messages = new Mongo.Collection("messages");
Shared-Methods
Meteor.methods({
sendMessage: function (messageText) {
if (! Meteor.userId()) {
throw new Meteor.Error("not-authorized");
}
Messages.insert({
messageText: messageText,
createdAt: new Date(),
username: Meteor.user().profile.username,
avatar: Meteor.user().profile.avatar,
});
}
});

Having issues with showing collection data in meteor

I am having collection issues in my Meteor project. I added the following code to my Resolutions.js file:
Resolutions = new Mongo.Collection('resolutions');
if (Meteor.isClient) {
Template.body.helpers({
resolutions: function() {
Resolutions.find({});
}
});
Template.body.events({
'submit .new-resolution': function(event) {
var title = event.target.title.value;
Resolutions.insert({
title: title,
createdAt: new Date()
});
event.target.title.value = "";
return false;
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
and added the following to my Resolutions.html file:
<head>
<title>Resolutions</title>
</head>
<body>
<div class="container">
<header>
<h1>Monthly Resolutions</h1>
<form class="new-resolution">
<input type="text" name="title" placeholder="A new resolution" />
<input type="submit" value="Submit"/>
</form>
</header>
<ul>
{{#each resolutions}}
{{> resolution}}
{{/each}}
</ul>
</div>
</body>
<template name="resolution">
<li>{{title}}</li>
</template>
After running the app I get zero errors but still the site does not return any of the collection value. I have no clue what is wrong with this project.
Template.body.helpers({
resolutions: function() {
return Resolutions.find({});
}
});
You forgot to use the return keyword.Remember that when creating a helper, you always need to return a value.

Limiting each inside of each based on context

Having trouble trying to pass some sort of context into my little test chan-clone.
Problem is I have threads, with replies. Showing just the threads works great, showing threads with replies based upon the threads they come from not so much.
Question is how do I send context on the outer each. Thank you so much for the help!
meteorchan.html
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
<h1>Meteor Chan - Let's do this</h1>
<form class="new-thread">
<input type="text" name="text" placeholder="New Thread" />
<button>Submit</button>
</form>
<br/>
{{#each threads}}
{{> thread}}
{{#each replies}}
{{> reply}}
{{/each}}
{{/each}}
</body>
<template name="thread">
<div class="thread">
<span>Anonymous</span> No. {{iden}}
<br>
{{text}}
</div>
<a class="reply" href="#">Reply</a> : <button class="purge">Purge</button>
<form class="new-reply {{this._id}}" style="display:none;">
<input type="text" name="text" placeholder="Add Reply" />
<input type="text" name="thread" value="{{this._id}}" style="display:none;" />
<button>Add New Reply</button>
</form>
<br>
<br>
</template>
<template name="reply">
<div class="reply">
{{text}}
<br>
{{parentThread}}
</div>
</template>
meteorchan.js
Threads = new Mongo.Collection("threads");
Replies = new Mongo.Collection("replies");
if (Meteor.isClient) {
Meteor.subscribe("threads");
Template.body.helpers({
threads: function () {
return Threads.find({}, {sort: {createdAt: -1}});
},
replies: function () {
return Replies.find({}, {sort: {createdAt: 1}});
}
});
Template.body.events({
"submit .new-thread": function (event) {
event.preventDefault();
var text = event.target.text.value;
var currentId = 0;
if(Threads.findOne({}, {sort: {createdAt: -1}})){
currentId = Threads.findOne({}, {sort: {createdAt: -1}}).iden;
}
Threads.insert({
text: text,
createdAt: new Date(),
iden: currentId + 1
});
event.target.text.value = "";
},
"submit .new-reply": function (event) {
event.preventDefault();
var text = event.target.text.value;
var thread = event.target.thread.value;
Replies.insert({
text: text,
createdAt: new Date(),
parentThread: thread
});
event.target.text.value = "";
}
});
Template.thread.events({
"click .purge": function (){
Threads.remove(this._id);
},
"submit .new-reply": function(event){
event.preventDefault();
},
"click .reply": function(){
$('.'+this._id+'.new-reply').css('display','inherit');
}
});
}
if (Meteor.isServer) {
Meteor.publish("threads", function () {
return Threads.find();
});
Meteor.publish("replies", function () {
return Replies.find();
});
}
You can refer to the context in the template helper using this.
So in your replies helper this refers to the current thread you are iterating over using the each.
You can do the following to only fetch replies for the corresponding thread:
replies: function () {
return Replies.find({
// this refers to the current thread
parentThread: this._id
}, {sort: {createdAt: 1}});
}

Meteor: collection empty after insert

I am new to meteor and got stucked and can't understand what am I doing wrong. Enlighten me please.
Here is the HTML file:
<body>
<h1>Do</h1>
{{#if activeTask}}
{{> currentTask}}
{{else}}
{{> newTask }}
{{/if}}
<div>
</div>
</body>
<template name="newTask">
<form>
<label>What<input type="text" name="what" placeholder="gimme an action"/></label>
<input type="submit" value="Go"/>
</form>
<!--
{{> inputAutocomplete settings=settings id="msg" class="input-xlarge" placeholder="action"}}
-->
</template>
<template name="currentTask">
<form>
<label>What<input type="text" name="what" placeholder="gimme an action"/>{{activeTask.what}}</label>
<div>4h 15m</div>
<input type="submit" value="Stop"/>
</form>
</template>
And here is the JavaScript file:
tasks = new Mongo.Collection('tasks');
if (Meteor.isClient) {
Template.body.helpers({
activeTask: function() {
var task = tasks.findOne(
{
endAt: null
},
{
sort: {
startAt: -1
}
}
);
console.log(task);
return task;
}
});
Template.newTask.events({
'submit' : function(event) {
event.preventDefault();
var now = Date.now();
var what = event.target.what.value;
tasks.insert({ what: what, startAt: now, endAt: null });
}
});
}
It successfully adds a new document into the database and logs this in the helper activeTask. One step later it logs no task at all. It has gone. But why?
If you don't have the package autopublish (https://atmospherejs.com/meteor/autopublish) installed, you need to create a publication (client-side) and subscription (server-side):
if (Meteor.isServer) {
Meteor.publish('tasks', function () {
return tasks.find();
});
}
if (Meteor.isClient) {
Meteor.subscribe('tasks');
}
I've also explained working with collections in a recent blog article.

Resources