API not returning suspended fields properly

AI-generated summary

A recent change in the Discourse API has resulted in inconsistent behavior when retrieving suspended user data. The suspended field is now sometimes null despite suspended_at having a non-null value. Geoffrey_Challen reported this issue, which affects scripts that rely on the suspended field to determine if a user is suspended.

According to eviltrout, the issue is not a regression, but rather a change in the API behavior. The suspended field is now defined as suspended_till && suspended_till > DateTime.now, which can result in a user being returned as not suspended if the suspension period has expired, even if suspended_at has a value.

To address the issue, eviltrout has made two changes to the API:

  • suspended will always be true or false, eliminating the need to check for null values.
  • suspended_at and suspended_till will only be returned if suspended is true, reducing the JSON payload size.

The changes have been committed to the Discourse repository: https://github.com/discourse/discourse/commit/f73a3cc0d4b9d7e8c1fbf2a4309397074ce4ec02.

In the past the API returned a user object with suspended: true (or some non-null value) when a user was suspended. A recent change seems to break that behavior. Now, suspended_at can be non-null while suspended is null.

Here is an example snippet returned by the API:

  "title": null,
  "suspended_at": "2017-10-11T15:11:26.936Z",
  "suspended_till": null,
  "suspended": null,
  "blocked": false,

This seems like a recent regression, since scripts that I wrote in August that relied on this behavior only recently stopped working properly. I’m on 1.9.0.beta12.

Unlikely to be a regression, the api changed as @eviltrout changed it.

OK. What’s the new correct way to interpret these fields? It’s seems counterintuitive for suspended_at to be set while suspended is null.

1 лайк

Can you be more specific about which API you’re using to get this information?

Also do you have steps to reproduce this? Looking at the unsuspend method, it should be clearing out suspended_at.

2 лайка

I’m grabbing the users from admin/users/list/active.json. I can provide more of the script if you’d like, but it uses that list to determine if there are users that should be suspended. (I’m using this for a class, so as students drop we suspend them indefinitely so that they can’t continue using the forum.) I use admin/users/<id>/suspend to suspend these users.

Back in August when I first wrote this, a check for user.suspended == null on the list of active users was sufficient to determine if a user was suspended. But then I noticed that some users were being repeatedly suspended, and realized that suspended was not being set to a non-null value as reported above.

Note that unsuspend probably has nothing to do with what I’m seeing—I never unsuspend users, since students don’t typically come back when they drop. (This did happen once, but I handled it manually.) The problem could be in the suspend method.

1 лайк

I reviewed the code and it turns out suspended? is simply defined as suspended_till && suspended_till > DateTime.now.

A user could be returned as not suspended if the period of time simply expired. suspnded_at in that case would still have a value because they were suspended then. I don’t think this is strictly a bug, as suspended would still be correct.

I did make two changes to make the API less confusing though:

  1. suspended will always be true or false, you don’t have to worry about null anymore.
  2. suspended_at and suspended_till will not be returned unless suspended is true. This shrinks our JSON payload which is nice.
7 лайков