XMPP block messages - xmpp

I am trying to block communications in my XMPP client (Built on top of strophe.js). The problem is it only blocks my messages to a contact I am trying to "mute" BUT doesn't block any incoming messages from that contact.
Here is the logic (based on http://xmpp.org/rfcs/rfc3921.html#privacy):
1) Add "bill#domain.me" to my "block" list
var recipient = "bill#domain.me"
var block = $iq({type: 'set'}).c('query', {xmlns: 'jabber:iq:privacy'}).
c('list', {name: 'block'}).
c('item', {type: 'jid', value: recipient, action: 'deny', order: 1}).
c('message');
2) Make this list active
var setListActive = $iq({type: 'set'}).c('query', {xmlns: 'jabber:iq:privacy'}).c("active", {name: "block"});
SGN.connection.sendIQ(setListActive);
What could be the problem?

I might be wrong but what I've understood is it is the way it should work.
If you check the list you were adding jids to you'll see that they are all there:
var getMyPrivacyList = $iq({type: 'get'}).c('query', {xmlns: 'jabber:iq:privacy'}).c("list", {name: "block"});
APP.connection.sendIQ(getMyPrivacyList,function success(response) { console.log(response) });
However if you want to block incoming messages you'd have to manually check senders's jids against this list every time message comes in.

you have to send unsubscribe presence to that buddy as well. and have to put an handler to handle presence type="unsubscribed". on that handler, send unsubscribe presence.
code for blocking friend
const blockFriend_Stanza=function(fromJid, friendJid,cb_success){
connection.send($pres({ to: friendJid, type: "unavailable", }));
connection.send($pres({ to: friendJid, type: "unsubscribe" }));
let UnblockIq=$iq({ 'type': 'set', 'id': 'blockFriend', from: fromJid })
.c("block", {xmlns: "urn:xmpp:blocking"}).c("item", {jid: friendJid});
connection.sendIQ(UnblockIq,
response=>{
console.log("onClick_lnkBlockFriend",response)
if(response.getAttribute("type")=="result"){
cb_success();
}
},
error=>{
console.log("onClick_lnkBlockFriend Error",error)
}
);
let updateRosterIq=$iq({ 'type': 'set', 'id': 'acceptedReq' })
.c("query", {xmlns: Strophe.NS.ROSTER}).c("item", {jid: friendJid,ask:null, subscription: "remove"});
connection.sendIQ(updateRosterIq,response=>{ console.log("onClick_lnkBlockFriend_rosterRemoval",response)},error=>{ console.log("onClick_lnkBlockFriend_rosterRemoval Error",error)});
}
Code for unsubscribe handler
function onPresence(presence) {
console.log("presense obj",presence);
var presence_type = $(presence).attr('type'); // unavailable, subscribed, etc...
var from = $(presence).attr('from'); // presence coming from jabber_id
var to = $(presence).attr('to'); // presence coming to jabber_id
if(presence_type == 'unsubscribe')
{
connection.send($pres({ to: from, type: "unsubscribed" }));
connection.send($pres({ to: from, type: "unavailable", }));
}
return true;
}

Related

Axios/mongodb request, PromiseState stuck on pending, then() part is not called

I'm trying to update my mongodb database in javascript by accessing some documents from the database, changing a specific document and then performing a patch request via axios.
When I get to the patch request I'm able to update the database however the promise is stuck on pending and thus, the then() part of the code is not run.
This is the main structure of the code:
In the first part the documents are requested from the database via axios.get:
function updateDocument(someinputdata){
g = axios.all([axios.get('/getData1),axios.get('/getData2)])
.then(response => {
Data1 = response[0].data;
Data2 = response[1].data;
adjustData(Data1,Data2);
});
}
In the second part a specific document is changed and a patch request is called:
function adjustData(Data1,Data2){
...getting specific document and change value from specific field...
var newRec = {
title: "dummyTitle",
rate: newRateValue
};
promise = axios({
url: '/patch/The Real Title',
method: 'PATCH',
data: newRec,
headers: { "Content-Type": "application/json" }
})
.then(() => {
console.log('I want this text to display but it doesn't')
});
}
If I console.log(promise):
Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined
On the server side I have this:
router.patch('/patch/:title', (req,res) => {
const updatedPost = Model.updateOne(
{ "title": req.params.title},
{ $set: { "rate" : req.body.rate}},
(err, result) => {
if(err) {
console.log(err);
throw err;
}
})
.then(
console.log('This text is displayed');
)
})
I want to use the first then() part to update some HTML
Why is the patch request stuck on pending (so not fulfilled or rejected)?
I've figured out what my problem was.
I needed to add
res.json({msg: "Your data has been saved"});
to the code on the server side.

How do I query a particular field in loopback 4 through the repository?

I want to enforce uniqueness so I would like to see if there are any other emails and usernames that are similar to the one posted to this route. How do I do that through the repository, it keeps on asking about a filter which I see but cannot get my head around it.
#post('/users', {
responses: {
'200': {
description: 'User model instance',
content: {'application/json': {schema: {'x-ts-type': User}}},
},
},
})
async create(#requestBody() user: User): Promise<User> {
//check : User= await this.userRepository.create(user);
//#param.query.object('filter', getFilterSchemaFor(User)) filter?: Filter;
// var check:any=await this.userRepository.find(filter);
//filter: Filter;
var check: User = await this.userRepository.find({email:user.email});
var isNotPresent: boolean = true;
// check.forEach(function(val){
// });
// if(isNotPresent)
return await this.userRepository.create(user);
}
A Filter object has the following properties that can be used to define a query and it's response:
where: Used to define a query. In your case, you would like to find existing users with the same email and username as provided in the request body.
fields: To specify fields that you would like to include or exclude in the response of your query. Every object in the array returned by find() will have only those fields which are set to true in the fields object.
offset, skip, limit and order: Used for pagination.
So, in your case, assuming a 'user' has an 'email' and an 'username', the filter object would look like the following:
const filter: Filter = {
where: {
'email': user.email,
'username': user.username
},
fields: {
email: true,
username: true
},
offset: 0,
limit: 10,
skip: 0,
order: [],
};
And your call to the repository method would look like the following:
var check: User = await this.userRepository.find(filter);
My first SO answer. Hope this helps.

MongoDB update a specific item of sub document (array) based on condition?

I have a PostSchema which has a property array called votedBy:[],this is of type votedBySchema.Like below:
var votedBySchema = new Schema({
voteType:{
type:Boolean,default:false
},
voter:{
type:Schema.Types.ObjectId
}
});
const PostSchema = new Schema({
_authorId:{
type:Schema.Types.ObjectId,
required:true
},
title:{
type:String,
required:true
},
body:{
type:String,
},
date:{
type:Date
},
hidden:{
type:Boolean,
default:false
},
popularity:{
type:Boolean
},
votedBy:[{
type:votedBySchema,
}]
});
Now I fire a patch request from postman with to url /post/:postId.Here I run a middleware which checks if user requesting has a valid token.And put userObject and token on req object.
Next I want that if user is author of the post then he can change everything about the post but if he is not the author then he can only change popularity i.e upVote or downVote.
My logic was that every voting person must be registered in votedBy array.
like:
votedBy:[
{voteType:true,voter:'abcd#gmail.com'}, //upvote
{voteType:false,voter:'pqrs#gmail.com'}//downvote
]
As Email is unique one must only be able to upVote or downVote so unique entry on basis of email in votedBy.
my route logic code:
app.patch('/post/:postId',authenticate,(req,res)=>{
console.log("[server.js]=>request ${req.method} to ${req.url}")
let body = _.pick(req.body,["title","body","popularity","hidden"])
let user = req.user;
let userId = user._id;
let postId = req.params.postId;
Post.findById(postId).then((post)=>{
let oldPost = post;//No use in code
console.log(`Found post ${post}`);
let postAuthorId = post._authorId.toString();
if(postAuthorId == userId){
post.title = body.title || post.title;//new,old
post.body = body.body || post.body;
post.hidden = body.hidden ||post.hidden;
post.update(post,{new:true}).then((postUpdated)=>{
console.log("Post Updated");
res.send(postUpdated);
});
}
else{
let voter = user.email;
console.log("\n voter is \n",voter)
let voteType = body.popularity;
//below code needs to be changed
/* post.update(
{
$set:{
'votedBy.$.voteType':voteType,
'votedBy.$.voter':voter
}
},
{
new:true
}
).then((iDontKnow)=>{
console.log('I dont know',iDontKnow);
res.send(post);
})*///Update or push the votedBy array for voter
}
});
});
Note I want to give a voting feature same as fb/youtube.
Also suggest if there is any other way around.
Idea of doing this is fine but if I would have implemented this will have kept userId for mapping rather than user email.
Eventually you will have that post from front end so you can send value from front end, but that will not be a that good a method.
post.findOneAndUpdate( { userId : 'id of user from session' }, { "votedBy.$. voteType" : "true/false"}, { upsert : true }, callback );
So you need to perform find operation first to get value of vote type for particular user and then update it
Route code will be something like
dbOperation.getPostData(request.body.postId, userId , (err,result)=>{
if(err){ //log the error}
else if(result!=undefined){
dbOperation.updatePost(request.body, (err,result)=>{
if(err){ //log the error}
else{
response.json({message:'update',code:200,success:true});
}
});
else{
response.json({message:'post not found',code:404,success:false});
}
});

MERN Stack: Saving Form Data to mLab - Formatting Issue

I am getting the data from my form to my mLab but it is formatted in a way i don't like. it comes though like this
{ '{"email":"ben#benjamin.com","message":"not what i want"}': '' }
and even worse it saves as this
"data": "{\"{\\\"email\\\":\\\"ben#benjamin.com\\\",\\\"message\\\":\\\"this is ridiculous\\\"}\":\"\"}"
so it is setting my data as the key to nothing basically. i resorted to changing my Schema to an Object just so i can save something. ideally i want a key for each piece of data. and i want to be able to access it later. i couldn't get body parser to work so i am using express-formidable as middleware. there are alot of moving parts and if i change things around i crash the server and get error no matter what i do. okay here is some of the code from both sides.
SERVER CODE:
var formSchema = new Schema({
data: Object
})
app.use(formidable());
app.post('/contact', function(req,res,next){
console.log(req.fields)
var item = JSON.stringify(req.fields)
var form = new Form({data: item
}).save(function(err,data){
if(err) throw err
if(data) res.json(data)
})
})
CLIENT SIDE CODE
submitData(e){
e.preventDefault();
let email = this.state.value;
let msg = this.state.value2;
let data = {
email: email,
message: msg
}
fetch('/contact', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: JSON.stringify(data)
})
.then((response) => response.json())
.then((responseData) => {
console.log("Response:",responseData);
this.setState({
value: "",
value2: "",
status: "THANKS FOR CONTACTING ME I'LL BE IN TOUCH SOON"
})
}).catch((error) => {
console.log(error)
})
}
this is driving me insane. ideally i would like to do it right. or somehow access the object and get at the email and message keys and just change my Schema. then i could assign the keys in my new Form(... section
In a bizarre twist of events i solved it sort of. this can't be the best way but it works. i would still like to know where along the line i went wrong. i saw a tutorial where the form data was easily saved...granted in wasn't from a react front end...anyway this is what i did
My Custom Solution
var formSchema = new Schema({
email: String,
message: String
})
app.use(urlencodedParser);
app.post('/contact', function(req,res,next){
var item = Object.keys(req.body)
var o = JSON.parse(item[0])
var e = o.email
var m = o.message
console.log(e)
//var item = JSON.stringify(req.fields)
var form = new Form({email: e,message: m
}).save(function(err,data){
if(err) throw err
if(data) res.json(data)
})
})
i switched back to body-parser from formidable but either way i was getting that weird object
i still don't know why my data object was {'{'key':'value'}':''} i thought my problem was on the server side...but maybe it is something with how i send the POST. someone smarter and more experienced isnt hard to find :)

Document disappears after being inserted into db in Meteor

trying to add to my very simple collection using
Template.home.events({
'click #send-button': function(e, t) {
e.preventDefault();
msg = {
from: Meteor.user()._id,
to: Meteor.user().penpal,
sent: new Date(),
message: $('#message').val()
};
messages.insert(msg);
console.log(messages.find().fetch());
}
})
in collections.js I have
messages = new Mongo.Collection('messages');
messages.allow({
'insert': function (userId,doc) {
return true;
}
});
message gets inserted but the console shows that it is being overwritten every time, eg it adds my new message but does not keep all old messages as well. when I try to render messages using
Template.home.helpers({
'messages': function(){
return messages.find().fetch();
}
})
and then
{{#each messages}}...{{/each}}
in html I get the messages appearing for the blink of an eye and then disapearing again.
please help! I am desperate!
Based on the Q&A, it appears you simply need to publish the collection and subscribe to it:
server:
Meteor.publish('myMessages',function(){
const me = this.userId;
if ( me ){
return messages.find({ $or: [{ from: me },{ to: me }]});
}
this.ready();
});
(in the code above the collection is being filtered to messages that are pertinent to the current user, you can define your own filters as required).
client:
Meteor.subscribe('myMessages');