Is there a way to post as an arbitrary user when creating a new post/topic using the Discourse API?


(John Lynch) #1

My friends and I were heavy users of Google Spaces. When Google announced that they were shutting Spaces down, I successfully scraped the site to pull down all our topic/post data in an ad-hoc JSON format. I also started hosting a Discourse server so that we could carry on our conversations there without having to worry about someone pulling the plug on our community. (And, it’s been a great experience thus far; much thanks to the Discourse community.)

What I’d like to do now is to get these old posts into Discourse. My hope was that I would be able to use the Discourse HTTP API to do this so that I could write my tools in C#, where I’m most comfortable (my Ruby knowledge is shallow and rusty, having only ever used it for minor things). After scuffling around for a little bit, I have managed to create a new topic through the API, but the new topic is always posted under that “admin” account that I pass as the “api_username” parameter to the API call. To be able to successfully import my old Spaces content, I need to be able to indicate which user created the topic/post. There doesn’t seem to be a way to do this using the API.

So: how do I indicate which user created a topic/post when using the Discourse API?

Am I missing something? Or am I going about this the wrong way? Is there a better way to import old content? Will I be able to do this using the API, or am I gonna have to get my hands dirty and run some Ruby code server side?

Any help greatly appreciated.

EDIT: I did try setting “api_username” to be the username I wanted, but that did not seem to work, netting me a 403 error, I believe. Not all my users are admins, naturally.


(Matt Palmer) #2

What API key are you using? The system-level one should, I believe, allow you to impersonate any other user via the api_username query parameter.


(John Lynch) #3

I created an API key through /admin/api/keys. The user is set to “All Users.”


(John Lynch) #4

Here’s some more detail:

When I POST this:

https://www.myforum.com/posts.json?api_key=theapikey&api_username=admin&title=test&category=15&raw=isatest

My topic is successfully created.

When I POST this:

https://www.myforum.com/posts.json?api_key=theapikey&api_username=John&title=test&category=15&raw=isatest

I get 403 Forbidden and the topic is not created. Both “John” and “admin” are currently existing users. “admin” is an admin account (obviously); “John” is a trust level 4 moderator, but not an admin.


(Matt Palmer) #5

How mysterious. What do the Rails logs say? (/var/discourse/shared/app/log/rails/production.log)


(John Lynch) #6

Here’s what I see in the log:

Started POST "/posts.json?api_key=[FILTERED]&api_username=John&title=test3&category=15&raw=isatest3" for 99.4.166.235 at 2017-04-24 00:30:39 +0000
Processing by PostsController#create as JSON
  Parameters: {"api_key"=>"[FILTERED]", "api_username"=>"John", "title"=>"test3", "category"=>"15", "raw"=>"isatest3"}
Can't verify CSRF token authenticity
Completed 403 Forbidden in 44ms (Views: 0.2ms | ActiveRecord: 6.6ms)`

(Sam Saffron) #7

Are you 100% sure the username is “John” and that your are referring to “username” here as opposed to “name”


(John Lynch) #8

Yes. When I go to the website to log in as my non-admin user account, I type “John” in as my username. When people @ me they “@John”. And the capitalization is just as you see here: normal English capitalization. The forum is small and private for acquaintances of mine, so conforming usernames to a first name basis policy keeps conversations more natural (and, not coincidentally, mimics how Spaces displayed conversations).

EDIT: Good question though, and wholly appropriate. You never know how a user might be confused.


(John Lynch) #9

I spent some time trying to debug this issue this evening, and I made some progress:

  1. I still get 403 Forbidden errors when I attempt to POST a JSON payload as string content with api_key and api_username in the header. I’m sure I’m simply not doing something correct here on my application’s side. I’m new to this whole web thing. :wink:
  2. However, I did discover why I was getting 403 Forbidden when sticking the payload directly in the URL (as above): the category I was attempting to post a new topic to had its permissions set to admins group only, and the user I was attempting to post as was not an admin. When I set that category up, I made it admin only so that I could do API testing in an isolated place; it didn’t occur to me that this would prevent me from posting as non-admins in that category using the API. Once I gave the user I was attempting to post as permission to create in that category, it worked right away. I think the whole CSRF token message in the logs was a red herring. The answer just came to me out of the blue; my debugging efforts didn’t really net me much.

So yeah: you get 403 Forbidden when attempting to post in a category as a user that doesn’t have permission to post in that category. Shocking! I guess part of me was thinking that by using the API key, I was basically overriding things like this. Apparently not. So this turns out to be almost entirely user error and I apologize for wasting people’s time. It would be nice if the logs were more clear about why a POST failed (or maybe they would be if I knew how to adjust Rails’ log level, but I don’t). Thanks for being patient with me!


(Sam Saffron) #10