stream-js icon indicating copy to clipboard operation
stream-js copied to clipboard

own_reactions bringing in the first like

Open logan-jobzmall opened this issue 7 years ago • 9 comments

Hi,

We are having an issue where the own_reactions like object (no matter what user is using the feed) is populated with the first like that was done on that activity. This is an issue because then it looks like you have liked something when you haven't, and the logic on our application states that if you have an own_reaction that you can't like it again, but can dislike it. It then tries to remove the like of another user. This is a serious bug that we are experiencing and it is in production. This is verified just from looking at the stream API calls. Thank you.

logan-jobzmall avatar Jan 02 '19 21:01 logan-jobzmall

@logan-jobzmall can you send the steps to reproduce this to Stream's support?

tbarbugli avatar Jan 03 '19 09:01 tbarbugli

@logan-jobzmall i've tried to reproduce this via API calls and javascript client and couldn't succeed. My initial assumption is that maybe you read the feeds with the same user token, thus yielding the same reaction.

Here is the code snippet I've used to try and reproduce this.

const stream = require('getstream');

const apiKey = 'YOUR_API_KEY';
const apiSecret = 'YOUR_API_SECRET';
const appID = 'YOUR_APP_ID';

const srvClient = stream.connect(
	apiKey,
	apiSecret,
);
const ericUser = stream.connect(
	apiKey,
	srvClient.createUserToken('eric-1'),
	appID,
);
const joshUser = stream.connect(
	apiKey,
	srvClient.createUserToken('josh-1'),
	appID,
);
const maxUser = stream.connect(
	apiKey,
	srvClient.createUserToken('max-1'),
	appID,
);

function checkOrFail(reactions, expectedID) {
	if (reactions === undefined || reactions.length !== 1) {
		throw Error('reactions have incorrent size!');
	}
	if (reactions[0].id !== expectedID) {
		throw Error(`Mismatch: Expected: ${expectedID}, actual: ${reactions[0].id}`);
	}
}

async function test() {
	//add an activity to a feed
	let feed = srvClient.feed('user', 'bob');
	const activity = await feed.addActivity({
		actor: 'bob',
		verb: 'eats',
		object: 'burger',
		foreign_id: 'burger-1',
		time: new Date(),
	});

	//eric likes this
	const ericLike = await ericUser.reactions.add('like', activity.id);

	//josh comments
	const joshComment = await joshUser.reactions.add('comment', activity.id, {
		text: 'awesome bro',
	});

	//max likes
	const maxLike = await maxUser.reactions.add('like', activity.id);

	const enrichReactions = { reactions: { own: true } };

	//eric reads the feed
	feed = ericUser.feed('user', 'bob');
	let response = await feed.get(enrichReactions);
	checkOrFail(response.results[0].own_reactions.like, ericLike.id);

	//max reads the feed
	feed = maxUser.feed('user', 'bob');
	response = await feed.get(enrichReactions);
	checkOrFail(response.results[0].own_reactions.like, maxLike.id);

	//josh reads the feed
	feed = joshUser.feed('user', 'bob');
	response = await feed.get(enrichReactions);
	checkOrFail(response.results[0].own_reactions.comment, joshComment.id);
}

test();

Link512 avatar Jan 03 '19 12:01 Link512

@tbarbugli @Link512 I find that to be odd. After double checking my code, it seems we are not. We grab the current user from our backend (using our JWT auth system) and pass that user’s ID to the PHP client function createUserSessionToken. After that we pass that to our JavaScript client initialization. We had to two users logged in on different computers, liked an activity on one, refreshed, then it showed own reactions on the other computer from the other user on the other computer. We know the user session isn’t being crossed because we can continuously refresh our site on any client and it’s the correct user so there isn’t anything wrong with our JWT system. Now remember, commenting works really well! It’s just likes at this point.

PHP (Laravel) Code:

public function getSessionToken(Request $request){
        $userId = Auth::id();

        if (!$userId){
            return response()->success(null);
        }

        return response()->success($this->feedManager->createUserSessionToken($userId));
    }


// FeedManager's createUserSessionToken is just using the underlying client

public function createUserSessionToken($userId)
    {
        return $this->client->createUserSessionToken($userId);
    }

TypeScript:

 this.user.streamToken(true).subscribe((token: string) => {
                    if (token) {
                        this._client = stream.connect(this.configService.getSettings('data.stream.app_key'), token, this.configService.getSettings('data.stream.app_id'));

                        // Set user and update because setuser doesn't seem to update user 
                        (this._client as any).setUser({
                            first_name: val.first_name,
                            last_name: val.last_name,
                            profile_image: val.profile_image,
                            professional_title: val.professional_title,
                            location: val.location,
                            slug: val.slug,
                            user_type: val.user_type.toString()
                        });
                        (this._client as any).user(val.id).update({
                            first_name: val.first_name,
                            last_name: val.last_name,
                            profile_image: val.profile_image,
                            professional_title: val.professional_title,
                            location: val.location,
                            slug: val.slug,
                            user_type: val.user_type.toString()
                        })
                        this.init();
                    }
                })

logan-jobzmall avatar Jan 06 '19 16:01 logan-jobzmall

could you capture the HTTP requests and send them to us? Since Github issues are public, I suggest sending them to our support ([email protected]) or to me directly on Keybase (tbarbugli)

tbarbugli avatar Jan 06 '19 18:01 tbarbugli

@tbarbugli absolutely. Will send stuff over on Keybase

logan-jobzmall avatar Jan 07 '19 17:01 logan-jobzmall

having the same issue in a project—was this issue resolved?

jryom avatar Mar 26 '19 13:03 jryom

@jesperryom it was not an issue with the API or the JS client @logan-jobzmall if you still remember it (and can share); it would be great if you could put here a few words about what went wrong for you

tbarbugli avatar Mar 26 '19 16:03 tbarbugli

How was this resolved? I am facing the same issue...

callmekatootie avatar May 13 '19 10:05 callmekatootie

I have been facing the same issue and I think I have discovered where the issue lies. I tried to connect via the front end client and get the activities with reactions, where everything was working fine. Whereas if I tried to get the activities via the back end client, the own_reactions field wasn't populated as expected.

So the problem is if you use the stream.connect function with your api secret as the second parameter, you won't get the expected results. It seems like stream.connect doesn't work as expected if the user token isn't supplied to it.

So as a workaround you could first connect via the api secret, get the token and then connect again via the token:

const client = stream.connect(API_KEY, SECRET, APP_ID);
const token = client.createUserSessionToken(userId);
const newClient = stream.connect(API_KEY, token, APP_ID);

const data = await newClient.feed('timeline', userId).get({ reactions: { own: true, counts: true } });

kapobajza avatar Oct 17 '19 12:10 kapobajza