Node-Craigslist syntax for details - javascript

Hello I am using the package node-craigslist https://github.com/brozeph/node-craigslist, and am hoping that someone can help me with some syntax with the details method.
In his documentation, he gives the example
client
.list()
.then((listings) => client.details(listings[0]))
.then((details) => {
console.log(details);
})
.catch((err) => {
console.error(err);
});
I currently have working the code to get the listings, but not the details. Below is my section of code where I retrieve the listings.
client
.list(options)
.then((listings) => {
listings.forEach((listing) => {
console.log(listing);
searchResults.title[counter] = listing.title;
searchResults.date[counter] = listing.date;
searchResults.location[counter] = listing.location;
searchResults.url[counter] = listing.url;
searchResults.price[counter] = listing.price;
counter++;
if(counter === listings.length) {
socket.emit('redirect'); //change to /results.ejs if done looping
};
});//end of listings foreach
});
I have been trying to incorporate the details into my own code unsuccessfully. Does anybody have any knowledge on how I can do this? Thanks.

You need to pass in a listing object into the method. In his example, he just grabs the most recent listings without any search options, then passes in the first listing from that array of listings. But you could obviously customize the search and the options.
client
.list()
.then((listings) => client.details(listings[0]))
.then((details) => {
console.log(details);
})
.catch((err) => {
console.error(err);
});
Depending on how the rest of your code is structured, you need to determine when to pass a specific listing. In my app that I built with this package, I make the initial search request that returns all the listings, and then when the user clicks on a listing for a search term, I make another request passing along that specific listing OBJECT and then it returns the details.
To be even more specific ...
On the client side the user searches, I emit that to the server then make the search request.
Once the request is finished I emit the results back to the client and then display the information to the user and store each listing object inside a custom data attribute inside each listing for later use.
Once the user clicks on a specific listing, I grab the object from the data-attribute and emit that to the server.
The server listens for that and makes the second DETAILS request using that listing object which is then emitted back to the clients browser.

Related

Is it possible to validate user in backend without user providing credientals?

I need to make a page with a button that fills certain text area with data from database. However I need it to also require administrator privileges.
Is it possible to have an API method that doesn't require credientals, but an Identity session instead? Ideally something that gets a HttpContext.User?
I don't know anything about JavaScript, I managed to put together this thing:
const url = '/api/clients/';
function getItems() {
fetch(url + document.getElementById('input').value)
.then(response => response.json())
.then(data => _displayItems(data));
}
function _displayItems(arrayOfResults) {
const textbox = document.getElementById('textbox');
textbox.value = "";
arrayOfResults.forEach(json => {
textbox.value += json.deviceIdentifier + "\n";
});
}
I have an API endpoint at http://localhost/api/clients/{string} that does a database query and it works as expected. But I can not allow just about anybody to access that data and I have trouble figuring out how to make user:
not provide his credentials
be able to use it with minimal effort (ie. just click the button and get results)
be unable to use this endpoint while not currently logged in on the website
Normally I just use this line to get the user that tries to access the controller:
var currentUser = await _userManager.FindByNameAsync(_userManager.GetUserName(HttpContext.User));
and go from there. But when my JS script is accessing the API it doesn't provide a way to validate using HttpContext, from what I'm seeing.

Firebase firestore: how to query relevant documents and then update each of them

I am developing a web app on Firebase/firestore, in which users can sign in and write their own posts. The data are stored in the following way:
-User information are stored as under collection('user').doc('uid').
-Information about posts the user has written are stored in collection('post').doc('postid'), and the doc has 'userinfo' and 'uid' fields. The 'userinfo' field contains exact copy of what is stored in 'uid' doc, just in object format.
Here are the operations that I want to do:
When the user changes the data, the changes are reflected in the document.
Look for the all the posts that the user has written based on 'uid' data, and then update userinfo in those data.
The last part is tricky for me. The Firebase documentations cover situations where the references are pretty much static, i.e. you know the exact path to write/update. What I am trying to do is look for a set of documents that is not necessarily static, and then update each of them.
Here is the code I wrote for this effort. The first part works without any problem. Of course, the second part doesn't work. :) What would be the code to do the do the second part?
const update = () => {
//This part is for updating user information. This works without any problem.
firebase.firestore().collection('user').doc(user.uid).update({
username: username1,
nickname: nickname1,
intro: intro1
})
.then(()=>{
//This part is for updating all of the document that the user has written based on 'uid' value. This doesn't work.
//Below code is probably way off, but it shows where I am going and what I am trying to do.
firebase.firestore().collection('post').where('uid','==',user.uid).get()
.then((querysnapshot)=>{
querysnapshot.forEach((doc)=>{
let ref=firebase.firestore().collection('post').doc(doc.id);
ref.update({
userinfo: {nickname:nickname1,username:username1,intro:intro1}
})
})
})
}).then(()=>{
alert("Successfully updated!");
window.location.href='/'+username1;
}).catch((error)=>{
alert("Error!");
})
}
Thanks a lot in advance!
What's the error that you get running this code? It seems on the right track for me.
But despite that, here are some suggestions to deal with this kind of update:
Don't do the second part on the client side, do it on the server side with a Firestore Trigger (create a onUpdate trigger in the user collection in your case): https://firebase.google.com/docs/functions/firestore-events.
The problem of doing in the client side, is because if the user closes the page/browser or the site goes offline in the middle of the update, you will have inconsistent data.
You don't need to recreate the DocumentReference after getting the query result, the docs returned already have a .ref that you can call .ref.update() directly.
EDIT: If you want to keep your original code (updating on client side), the problem of the navigation occurring before all the updates to conclude is because ref.update() returns a promise.
So the update queue is asynchronous being performed on database when the client navigates away.
To solve this, I would use a Promise.all() to wait all updates being completed.
firebase.firestore().collection('post').where('uid','==',user.uid).get()
.then((querysnapshot)=>{
const promises = [];
querysnapshot.forEach((doc)=>{
promises.push(doc.ref.update({
userinfo: {nickname:nickname1,username:username1,intro:intro1}
});
});
Promise.all(promises).then(()=>{window.location.href='/'+username1;});
});
Or using the await syntax (I think it's easier to maintain and understand):
const querysnapshot = await firebase.firestore().collection('post').where('uid','==',user.uid).get();
const promises = [];
querysnapshot.forEach((doc)=>{
promises.push(doc.ref.update({
userinfo: {nickname:nickname1,username:username1,intro:intro1}
});
});
await Promise.all(promises);
window.location.href='/'+username1;

How to get only one user instead of a list?

I try to get from a list of users to only one user and display his profile on another page.
I want to do so with the routerLink and passing on an id of this specific user to the next page.
The routing is working, Im directed to the profile page but when I log the results of the http request I still get back the whole list of users like in the users page instead of the details of one user.
I have tried many things like changing the path of the url in my user.service.ts but that didn't solve the problem I even got 404 request errors when using this path ${this.url}/users/${id}/ instead of ${this.url}/users/?i=${id}/ (where its working).
The api docs is saying though that in order to retrieve one single user its http://1234//users/{id}/ it this scheme while id is an integer. But when I want to apply that scheme I get the 404 error.
Thats why I have to use the ?I= version but there the problem is I only get the full list of users on the next page.
MY CODE:
user.service.ts
// get a user's profile
getUserDetails(id): Observable<any> {
return this.http.get(`${this.url}/users/?i=${id}/`); // why add ?i
}
user.page.ts
// get all users in the users page
getAllUsers() {
this.userList = this.userService.getList()
.pipe(map(response => response.results));
}
user.page.html
<ion-avatar class="user-image" slot="start" [routerLink]="['/','profile', 'user.id']">
<ion-img src="assets/22.jpeg"> </ion-img>
</ion-avatar>
profile.page.ts
information = null;
...
ngOnInit() {
// Get the ID that was passed with the URL
let id = this.activatedRoute.snapshot.paramMap.get('id');
// Get the information from the API
this.userService.getUserDetails(id).subscribe(result => {
this.information = result;
console.log(result);
});
}
It seems like the url is wrong. If it was me I would console.log the url and compare it to the docs. Heres a snippet to try a few variations:
const id = 1;
const options = [
`${this.url}/users/?i=${id}/`,
`${this.url}/users/?i=${id}`,
`${this.url}/users/i/${id}/`,
`${this.url}/users/i/${id}`,
`${this.url}/user/?i=${id}/`,
`${this.url}/user/?i=${id}`,
`${this.url}/user/i/${id}/`,
`${this.url}/user/i/${id}`,
];
for (const option of options) {
try {
const response = await this.http.get(option);
console.log(options, response);
} catch (e) {
}
}
I would also consider dropping the second http request. If the first request returns all the required data you could just store it in a variable on the service.

Unable to Post to a Feed Group in GetStream

I'm currently using Stream to build Feeds in our React Native app.
I ran into a problem enabling users to post to a new board feed group I made.
Currently iOS only
Problem: I have created a "board" feed group and want to allow users to post to that feed group to save posts. I have enabled permissions for this as per: https://github.com/GetStream/react-activity-feed/issues/23 via support. Yet I am still unable to post to the "board" feed group but I'm still receiving a permissions error.
I'm using the SinglePost component from the official React Native GetStream library and have a save button on the activity component.
The save button opens a modal to allow a user to select a board and after a user selects a board the _saveBoard method is called. You can see the full method here.
_saveToBoard = item => {
let boardId = item.id;
console.log('boardId', boardId, this.props);
// // Add activity to selectedBoard
var selectedBoard = this.props.client.feed('board', boardId);
let activity_data = {
actor: this.props.client.currentUser.id,
verb: 'save',
object: `BoardPost:${generateId()}`
};
console.log('activity data', activity_data);
selectedBoard
.addActivity(activity_data)
.then(res => console.log('added activity', res))
.catch(err => console.log('error adding activity to board', err));
console.log('selectedBoard', selectedBoard);
};
Not sure where I went wrong and hoping its something I overlooked.
The default permission policies don't allow a user to add an activity with actor set to anything else than current user's reference. This restriction is only enforced client-side to make sure that users are not able to impersonate other users.
Changing actor from this.props.client.currentUser.id into this.props.client.currentUser.id will make sure that the activity is added with a user reference equal to current user.

MeteorJS - No user system, how to filter data at the client end?

The title might sound strange, but I have a website that will query some data in a Mongo collection. However, there is no user system (no logins, etc). Everyone is an anonymouse user.
The issue is that I need to query some data on the Mongo collection based on the input text boxes the user gives. Hence I cannot use this.userId to insert a row of specifications, and the server end reads this specifications, and sends the data to the client.
Hence:
// Code ran at the server
if (Meteor.isServer)
{
Meteor.publish("comments", function ()
{
return comments.find();
});
}
// Code ran at the client
if (Meteor.isClient)
{
Template.body.helpers
(
{
comments: function ()
{
return comments.find()
// Add code to try to parse out the data that we don't want here
}
}
);
}
It seems possible that at the user end I filter some data based on some user input. However, it seems that if I use return comments.find() the server will be sending a lot of data to the client, then the client would take the job of cleaning the data.
By a lot of data, there shouldn't be much (10,000 rows), but let's assume that there are a million rows, what should I do?
I'm very new to MeteorJS, just completed the tutorial, any advice is appreciated!
My advice is to read the docs, in particular the section on Publish and Subscribe.
By changing the signature of your publish function above to one that takes an argument, you can filter the collection on the server, and limiting the data transferred to what is required.
Meteor.publish("comments", function (postId)
{
return comments.find({post_id: postId});
});
Then on the client you will need a subscribe call that passes a value for the argument.
Meteor.subscribe("comments", postId)
Ensure you have removed the autopublish package, or it will ignore this filtering.

Categories