unauthenticated posts can not be deleted from the CLI while authenticated
Closed, ResolvedPublic



If a user creates a post locally, while not logged in (authenticated). Then later authenticates, they can not delete the previously created local post.


The CLI does not report any error, which leads the user to believe the post was deleted. However on running writeas posts, list in previous versions, the post remains. In fact visiting the URL does confirm it still exists.


The CLI should actually delete the post from the server as well as remove the line from the posts.psv file.

  • If there is some error along the way it should be reported back to the user. (CLI)
  • WriteFreely should check for a provided token before user auth on deletes.

Event Timeline

I'm getting back a 403 forbidden with the correct token, it must be getting returned by go-writeas in writeas.go c.delete().

the question is why


is it possible to see the server application logs for

I'm sending logs over from the dev server now, polled every 10 seconds. You can view on our team server with:

sudo tail -F /var/log/syslog | grep devwriteas

thanks @matt, they aren't verbose enough though. Only requests and their http status + method.

Can you verify requests (both login and delete) are going to the right environment with some logging on your end? If they are, I'll add some logging on the dev server.

matt triaged this task as High priority.Jun 2 2019, 11:03 PM

I found in go-writeas:

func (c *Client) doRequest(r *http.Request, result interface{}) (*impart.Envelope, error) {
	resp, err := c.client.Do(r)
	if err != nil {
		return nil, fmt.Errorf("Request: %v", err)
	defer resp.Body.Close()

	env := &impart.Envelope{
		Code: resp.StatusCode,
	if result != nil {
		env.Data = result

		err = json.NewDecoder(resp.Body).Decode(&env)
		if err != nil {
			return nil, err

	return env, nil

We are only returning the status code, not the response error because when we call doRequest we pass in nil as the result property and never decode the response body.

So in:

func (c *Client) deletePost(collection, identifier, token string) error {
	p := map[string]string{}
	endpoint := "/posts/" + identifier
		if collection != "" {
			endpoint = "/collections/" + collection + endpoint
		} else {
			p["token"] = token
	p["token"] = token
	env, err := c.delete(endpoint, p)
	if err != nil {
		return err

	status := env.Code
	if status == http.StatusNoContent {
		return nil
	} else if c.isNotLoggedIn(status) {
		return fmt.Errorf("Not authenticated.")
	} else if status == http.StatusBadRequest {
		return fmt.Errorf("Bad request: %s", env.ErrorMessage)
	return fmt.Errorf("Problem deleting post: %d. %s\n", status, env.ErrorMessage)

At the end, we return an empty string. This results in the error: Problem deleting: Problem deleting post: 403.

After modifying my module cache copy of the library, I get Problem deleting: Problem deleting post: 403. Post not found, or you're not the owner.

Which brings us to line 813 in posts.go of writefreely:

	affected, err := res.RowsAffected()
	if err != nil {
		if t != nil {
			log.Error("Rows affected err! Rolling back")
		return err
	} else if affected == 0 {
		if t != nil {
			log.Error("No rows affected! Rolling back")
		return impart.HTTPError{http.StatusForbidden, "Post not found, or you're not the owner."}

Any ideas @matt? I'm not very familiar with the writefreely application yet

I think I found the issue, the logic in this function on writefreely appears to check first if the accesstoken or user were found and proceed with that authentication, which will result in no affected rows. Lines 741-788, then an else which assumes the editToken instead.

I propose we rearrange the logic to first check if the edit token is present because we may not own the post but do have the token.


robjloranger renamed this task from unauthenticated posts can not be deleted while authenticated to unauthenticated posts can not be deleted from the CLI while authenticated.Jun 5 2019, 5:30 PM
robjloranger updated the task description. (Show Details)
robjloranger added a project: CLI.

Assuming the #117 fix works in your testing, after reviewing everything I do think this is the right solution.

I also put up #30 CLI which returns the errors during delete to the user. Then this can close.