I wrote a Meteor method for changing an object. Only the owner of the object should be able to edit properties.
The method thus checks for a match of the current user and the object owner. If it doesn't match, the method throws an exception with the cause.
This approach works, as the change does not hit the collection and the error object is returned to the client.
Nevertheless the edited property is not updated to reflect it's actual value. How can I trigger refreshing the value?
Additional info: I am using React on the frontend; the object is not updated explicitely in the frontend code (so the method seems to be run on the client side, too).
Some code (simplified, naming changed, obvious errors might not be in the original ;)
Client side:
saveCommentChanges(updatedComment) {
Meteor.call('comment.updateComment', updatedComment, function (error, result) {
if (error && error.error === "not-authorized") {
Session.set("errorMessage", "You are only allowed to change own comments.");
}
});
}
Server Side:
if (Meteor.isServer) {
Meteor.methods({
'comment.updateComment'(comment) {
check(comment, Object);
origComment = Comments.findOne(comment._id);
if (origComment.user != this.userId) {
console.log('user does not match');
throw new Meteor.Error('not-authorized');
}
let res = Comments.update(
{'_id': comment._id},
{$set: {date: comment.date,
comment: comment.comment}
}, {removeEmptyStrings: false});
}
}
To refresh in the client side after update:
this.subscribe('Comments');
See the example below in AngularJS meteor remove autopublish
for the front end to update correctly. The meteor server prompted me to do this In your case, the comments won't be filtered and you can filter the update based on the comment ID and the user. If no already existing comment is found, then the update will not work and you can catch throw an error.
if (Meteor.isServer) {
// This code only runs on the server
Meteor.publish('comments', function publishComments() {
return Comments.find({});
});
}
Meteor.methods({
'comment.updateComment'(comment) {
check(comment, Object);
origComment = Comments.findOne(comment._id);
// option 1
if (origComment.user != this.userId) {
console.log('user does not match');
throw new Meteor.Error('not-authorized');
}
// keep the same update here
// option 2
let res = Comments.update(
{ '_id': comment._id,'user': origComment.user},
{$set: {date: comment.date,
comment: comment.comment}
}, {removeEmptyStrings: false});
return res;
}
);
imports/component/stocks/stocks.html
<button type="submit" class="btn btn-success btn-sm m-2"
ng-hide="{{$ctrl.currentUser === null}}"
ng-click="$ctrl.buyStock(stock.name, 1)">
Buy 1 Share
</button>
imports/component/stocks/stocks.js
import angular from 'angular';
import angularMeteor from 'angular-meteor';
import template from './stocks.html';
import { Meteor } from 'meteor/meteor';
import { Stocks } from '../../api/Stocks.js';
import { UserStocks } from '../../api/UserStocks.js';
class StocksCtrl {
constructor($scope) {
$scope.viewModel(this);
this.subscribe('stocks');
this.subscribe('userStocks');
// Return the data mostly right now
this.helpers({
currentUser() {
return Meteor.user();
},
stocks() {
const selector = {};
// Show newest tasks at the top
return Stocks.find(selector, {
sort: {
name: 1
}
});
},
userStocks() {
return UserStocks.find({});
}
})
}
buyStock(stock, amt) {
console.log("Buying stock processing...");
// ADD TO UserStock
Meteor.call('userStocks.buy', stock, amt, function(error, result) {
if(error){
console.log(error.reason);
return;
}
// log to console
console.log("UserID: " + Meteor.userId() + "\n Username: " + Meteor.user().username
+ "\n Message: Purchase of " + amt + " shares of " + stock + " was successful.");
// alert the user
alert("Purchase of " + amt + " shares of " + stock + " was successful.");
});
console.log("Buying stock complete.");
}
}
export default angular.module('StocksApp', [
angularMeteor
])
.component('stocksApp', {
templateUrl: 'imports/components/stocks/stocks.html',
controller: ['$scope', StocksCtrl]
});
imports/api/UserStocks.js
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
export const UserStocks = new Mongo.Collection('userStocks');
if (Meteor.isServer) {
// This code only runs on the server
// Only publish tasks that are public or belong to the current user
Meteor.publish('userStocks', function getUserStocks() {
return UserStocks.find({
ownerID: { $eq: this.userId }
});
});
}
Meteor.methods({
'userStocks.buy' (stock, amount) {
// Make sure the user is logged in before inserting a task
if (!Meteor.userId()) {
throw new Meteor.Error('not-authorized');
}
// if currently exists, increase the amount by the amount purchased
// if it does not exit, the upsert true will create/insert
const newID = UserStocks.update(
{ ownerID: { $eq: this.userId }, stock: { $eq: stock } },
{ $setOnInsert: { ownerID: this.userId, stock: stock}, $inc: {amt: amount} },
{ upsert: true, returnNewDocument: true}
);
return newID;
}
});
server/main.js
import '../imports/api/Stocks.js';
import '../imports/api/UserStocks.js';
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.