API POST to /posts.json inconsistent between users

We have an admin api_key that we’re using to create new topics on behalf of users. So we POST this to the /posts.json endpoint:

const postBody = [
	"title": "Some new topic title",
	"category": "General",
	"raw": "the post of the forum topic...",
	"api_username": "admin_user",
	"api_key": "xxxxxxxxxxxxxxxxxx",
]

This works correctly so long as api_username belongs to the admin user. If we post on behalf of another user (by changing the api_username) then we get a 404 with the following error in the rails log:

Completed 404 Not Found in 39ms (ActiveRecord: 0.0ms)
ActiveRecord::RecordNotFound (Couldn't find Category with 'id'=General)

If we alter the API POST to use the integer ID of the “General” category instead of its textual name, it then works as expected.

Why does it allow textual category specification in the former case but not the latter?

Running v2.3.0.beta9 +424

3 Likes

Any thoughts here @blake?

1 Like

For legacy reasons and because for non-admins the code takes a different path and goes through a post_needs_approval? method that admins don’t need to go through where it searches for the category that doesn’t use the legacy find method (requires a category id).

Category.find(manager.args[:category]).require_topic_approval?

Now regarding the legacy reason mentioned above, I think we can now get rid of the “temporary” else statement in this block of code, based on these 5 year old comments, where an admin can specify a category by name:

# Temporary fix to allow older clients to create topics.
# When all clients are updated the category variable should
# be set directly to the contents of the if statement.
if (@opts[:category].is_a? Integer) || (@opts[:category] =~ /^\d+$/)
  Category.find_by(id: @opts[:category])
else
  Category.find_by(name_lower: @opts[:category].try(:downcase))
end

Also we don’t even have support for passing in the category slug so as an admin passing in “site-feedback” for the category would also fail.

Because the the web interface uses the category id when making api calls my vote is to actually rip out the old logic and require that a category id be specified instead of the category name. To get the id’s of all the categories you can make an api request to /categories.json. And then use those id’s for creating a topic.

I created a PR if we do want to unify the api and only allow category_id’s when creating a topic.

https://github.com/discourse/discourse/pull/7599

8 Likes

Blake’s PR was merged.

3 Likes

This topic was automatically closed after 2 days. New replies are no longer allowed.