JayOneTheSk8 / but-why-tho

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Y (Server)

Y is a platform for posting questions and asking more. Users can create posts and comments as long as they're all questions, encouraging deeper thought. Users can also follow each other and like and repost posts and comments. Posts and highly reposted comments are aggregated onto the front page. For a currated list, a user can view a front page of their followed users.

The frontend client of this server is located at https://github.com/JayOneTheSk8/why-client.

Table of Contents

Installation

Requires ruby-3.2.2 and postgresql

bundle install
bin/rails db:migrate

Run Server

bin/rails s

Lint (via Rubocop)

bin/rubocop

Run Test Specs

bin/rspec

Set up for HTTPS (Required for cross-site browser cookies)

Install openssl

# via Ubunutu
sudo apt install openssl

Create local key/certificate

# From top-repo level (lasts 1 year)
openssl req -x509 -sha256 -nodes -newkey rsa:2048 -keyout config/ssl/localhost.key -out config/ssl/localhost.crt -subj  "/CN=localhost" -days 365

Run server via puma config

bundle exec puma -C config/puma.rb

API Specs

Authentication

POST /sign_up

Creates a new User and signs them in.

Request

{
  "user": {
    "username": <string> 
    "display_name": <string>
    "email": <string>
    "password": <string>
    "password_confirmation": <string> # optional
  }
}

Response

{
  "id": <bigint>
  "username": <string>
  "display_name": <string>
  "email": <string>
}

POST /sign_in

Signs a User in.

Request

{
  "user": {
    "login": <string> # Username or email for user
    "password": <string>
  }
}

Response

{
  "id": <bigint>
  "username": <string>
  "display_name": <string>
  "email": <string>
}

GET /sign_out

Signs the User out.

Response

200 OK

GET /sessions

Returns the current logged in User.

Response

{
  "id": <bigint>
  "username": <string>
  "display_name": <string>
  "email": <string>
}

Users

GET /users/:username

Get the data of the User.

Response

{
  "id": <bigint>
  "username": <string>
  "display_name": <string>
  "email": <string>
  "current_user_following": <boolean>
  "post_count": <int>
  "following_count": <int>
  "follower_count": <int>
}

PUT /users/:id

Edits the User.

Request

{
  "user": {
    "display_name": <string>
    "email": <string>
  }
}

Response

{
  "id": <bigint>
  "username": <string>
  "display_name": <string>
  "email": <string>
  "current_user_following": <boolean>
  "post_count": <int>
  "following_count": <int>
  "follower_count": <int>
}

Posts

GET /posts

Gets all Posts by lastest creation date.

Response

[
  {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "comment_count": <int>
    "current_user_following": <boolean>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
    "comments": [
      {
        "id": <bigint>
        "text": <string>
        "created_at": <datetime>
        "reply_count": <int>
        "author": {
          "id": <bigint>
          "username": <string>
          "display_name": <string>
        }
      }
      ...
    ]
  }
  ...
]

GET /posts/:id

Gets the data of the Post.

Response

{
  "id": <bigint>
  "text": <string>
  "created_at": <datetime>
  "comment_count": <int>
  "current_user_following": <boolean>
  "author": {
    "id": <bigint>
    "username": <string>
    "display_name": <string>
  }
  "comments": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "reply_count": <int>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

POST /posts

Creates a new Post.

Request

{
  "post": {
    "text": <string>
  }
}

Response

{
  "id": <bigint>
  "text": <string>
  "created_at": <datetime>
  "comment_count": <int>
  "current_user_following": <boolean>
  "author": {
    "id": <bigint>
    "username": <string>
    "display_name": <string>
  }
  "comments": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "reply_count": <int>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

PUT /posts/:id

Updates a Post's text.

Request

{
  "post": {
    "text": <string>
  }
}

Response

{
  "id": <bigint>
  "text": <string>
  "created_at": <datetime>
  "comment_count": <int>
  "current_user_following": <boolean>
  "author": {
    "id": <bigint>
    "username": <string>
    "display_name": <string>
  }
  "comments": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "reply_count": <int>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

DELETE /posts/:id

Deletes a Post and its associated comments

Response

{
  "id": <bigint>
  "text": <string>
  "created_at": <datetime>
  "comment_count": <int>
  "current_user_following": <boolean>
  "author": {
    "id": <bigint>
    "username": <string>
    "display_name": <string>
  }
  "comments": []
}

GET /users/:user_id/posts

Gets the User's created Posts.

Response

[
  {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "comment_count": <int>
    "current_user_following": false
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
    "comments": [
      {
        "id": <bigint>
        "text": <string>
        "created_at": <datetime>
        "reply_count": <int>
        "author": {
          "id": <bigint>
          "username": <string>
          "display_name": <string>
        }
      }
      ...
    ]
  }
  ...
]

GET /users/:user_id/linked_posts

Gets all User's created Posts and reposted Posts and Comments

Response

{
  "user": {
    "username": <string>
    "display_name": <string>
  }
  "posts": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "post_type": <CommentRepost|PostRepost|Post>
      "like_count": <int>
      "repost_count": <int>
      "comment_count": <int>
      "post_date": <datetime> # datetime of post creation or repost
      "reposted_by": <string> # display name of reposter; optional
      "reposted_by_username": <string> # username of reposter; optional
      "user_liked": <boolean> # current user liked
      "user_reposted": <boolean> # current user reposted
      "user_followed": <boolean> # current user following author
      "replying_to": <string[]> # usernames of parent comment and post author; optional
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

GET /front_page

Gets the most popular Posts and reposted (at least 5 times) Comments by date and popularity.

Response

{
  "posts": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "post_type": <CommentRepost||Post>
      "like_count": <int>
      "repost_count": <int>
      "comment_count": <int>
      "post_date": <datetime>
      "user_liked": <boolean>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "rating": <int> # comment/post's popularity
      "replying_to": <string[]>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

GET /front_page_following

Gets the most popular posts and reposted comments by date and popularity; filtered by the current User's following list. Includes the User's posts and reposts as well.

Response

{
  "posts": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "post_type": <CommentRepost|PostRepost|Post>
      "like_count": <int>
      "repost_count": <int>
      "comment_count": <int>
      "post_date": <datetime>
      "reposted_by": <string>
      "reposted_by_username": <string>
      "user_liked": <boolean>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "rating": <int>
      "replying_to": <string[]>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

GET /posts/:post_id/data

Gets the Post's full data with its associated top-level comments.

Response

{
  "post": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "comment_count": <int>
    "like_count": <int>
    "repost_count": <int>
    "user_liked": <boolean>
    "user_reposted": <boolean>
    "user_followed": <boolean>
    "replying_to": null
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    },
    "comments": [
      {
        "id": <bigint>
        "text": <string>
        "created_at": <datetime>
        "comment_count": <int>
        "like_count": <int>
        "repost_count": <int>
        "user_liked": <boolean>
        "user_reposted": <boolean>
        "user_followed": <boolean>
        "replying_to": <string[]>
        "author": {
          "id": <bigint>
          "username": <string>
          "display_name": <string>
        }
      }
      ...
    ]
  }
}

Comments

GET /comments/:id

Gets the data of a Comment.

Response

{
  "id": <bigint>
  "text": <string>
  "created_at": <datetime>
  "reply_count": <int>
  "current_user_following": <boolean>
  "author": {
    "id": <bigint>
    "username": <string>
    "display_name": <string>
  }
  "post": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "comment_count": <int>
    "current_user_following": <boolean>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
  }
  "parent": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "reply_count": <int>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
  }
  "replies": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "reply_count": <int>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

POST /comments

Creates a new Comment.

Request

{
  "comment": {
    "text": <string>
    "post_id": <bigint>
    "parent_id": <bigint> # optional parent comment being replied to
  }
}

Response

{
  "id": <bigint>
  "text": <string>
  "created_at": <datetime>
  "reply_count": <int>
  "current_user_following": <boolean>
  "author": {
    "id": <bigint>
    "username": <string>
    "display_name": <string>
  }
  "post": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "comment_count": <int>
    "current_user_following": <boolean>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
  }
  "parent": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "reply_count": <int>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
  }
  "replies": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "reply_count": <int>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

PUT /comments/:id

Updates Comment's text.

Request

{
  "comment": {
    "text": <string>
  }
}

Response

{
  "id": <bigint>
  "text": <string>
  "created_at": <datetime>
  "reply_count": <int>
  "current_user_following": <boolean>
  "author": {
    "id": <bigint>
    "username": <string>
    "display_name": <string>
  }
  "post": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "comment_count": <int>
    "current_user_following": <boolean>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
  }
  "parent": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "reply_count": <int>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
  }
  "replies": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "reply_count": <int>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

DELETE /comments/:id

Deletes a Comment.

Response

{
  "id": <bigint>
  "text": <string>
  "created_at": <datetime>
  "reply_count": <int>
  "current_user_following": <boolean>
  "author": {
    "id": <bigint>
    "username": <string>
    "display_name": <string>
  }
  "post": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "comment_count": <int>
    "current_user_following": <boolean>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
  }
  "parent": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "reply_count": <int>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
  }
  "replies": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "reply_count": <int>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

GET /users/:user_id/comments

Gets the User's created comments.

Response

[
  {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "reply_count": <int>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    }
    "post": {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "comment_count": <int>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    "parent": {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "reply_count": <int>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
  }
  ...
]

GET /users/:user_id/linked_comments

Gets the User's created and reposted Comments.

Response

{
  "user": {
    "username": <string>
    "display_name": <string>
  },
  "comments": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "post_type": <CommentRepost||Comment>
      "like_count": <int>
      "repost_count": <int>
      "comment_count": <int>
      "post_date": <datetime>
      "user_liked": <boolean>
      "reposted_by": <string>
      "reposted_by_username": <string>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "replying_to": <string[]>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

GET /comments/:comment_id/data

Gets the Comment's full data with its associated post and optional parent and replies.

Response

{
  "comment": {
    "id": <bigint>
    "text": <string>
    "created_at": <datetime>
    "comment_count": <int>
    "like_count": <int>
    "repost_count": <int>
    "user_liked": <boolean>
    "user_reposted": <boolean>
    "user_followed": <boolean>
    "replying_to": <string[]>
    "author": {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
    },
    "post": {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "comment_count": <int>
      "like_count": <int>
      "repost_count": <int>
      "user_liked": <boolean>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "replying_to": null
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    },
    "parent": { # nullable
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "comment_count": <int>
      "like_count": <int>
      "repost_count": <int>
      "user_liked": <boolean>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "replying_to": <string[]>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    },
    "comments": [
      {
        "id": <bigint>
        "text": <string>
        "created_at": <datetime>
        "comment_count": <int>
        "like_count": <int>
        "repost_count": <int>
        "user_liked": <boolean>
        "user_reposted": <boolean>
        "user_followed": <boolean>
        "replying_to": <string[]>
        "author": {
          "id": <bigint>
          "username": <string>
          "display_name": <string>
        }
      }
      ...
    ]
  }
}

Likes

POST /comment_likes

Creates a new CommentLike.

Request

{
  "like": {
    "message_id": <bigint>
  }
}

Response

{
  "type": "CommentLike"
  "comment_id": <bigint>
  "user_id": <bigint>
}

DELETE /comment_likes

Deletes a CommentLike.

Request

{
  "like": {
    "message_id": <bigint>
  }
}

Response

{
  "type": "CommentLike"
  "comment_id": <bigint>
  "user_id": <bigint>
}

POST /post_likes

Creates a new PostLike.

Request

{
  "like": {
    "message_id": <bigint>
  }
}

Response

{
  "type": "PostLike"
  "post_id": <bigint>
  "user_id": <bigint>
}

DELETE /post_likes

Deletes a PostLike.

Request

{
  "like": {
    "message_id": <bigint>
  }
}

Response

{
  "type": "PostLike"
  "post_id": <bigint>
  "user_id": <bigint>
}

GET /users/:user_id/likes

Gets the Posts and Comments the User liked in order of Like.

Response

{
  "user": {
    "username": <string>
    "display_name": <string>
  }
  "likes": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "like_type": <PostLike||CommentLike>
      "like_count": <int>
      "repost_count": <int>
      "comment_count": <int>
      "liked_at": <datetime>
      "reposted_by": <string>
      "reposted_by_username": <string>
      "user_liked": <boolean>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "replying_to": <string[]>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

Reposts

POST /comment_reposts

Creates a CommentRepost.

Request

{
  "repost": {
    "message_id": <bigint>
  }
}

Response

{
  "type": "CommentRepost"
  "comment_id": <bigint>
  "user_id": <bigint>
}

DELETE /comment_reposts

Deletes a CommentRepost.

Request

{
  "repost": {
    "message_id": <bigint>
  }
}

Response

{
  "type": "CommentRepost"
  "comment_id": <bigint>
  "user_id": <bigint>
}

POST /post_reposts

Creates a PostRepost.

Request

{
  "repost": {
    "message_id": <bigint>
  }
}

Response

{
  "type": "PostRepost"
  "post_id": <bigint>
  "user_id": <bigint>
}

DELETE /post_reposts

Deletes a PostRepost.

Request

{
  "repost": {
    "message_id": <bigint>
  }
}

Response

{
  "type": "PostRepost"
  "post_id": <bigint>
  "user_id": <bigint>
}

Follows

POST /follows

Creates a Follow.

Request

{
  "follow": {
    "followee_id": <bigint>
  }
}

Response

{
  "follower_id": <bigint>
  "followee_id": <bigint>
}

DELETE /follows

Deletes a Follow.

Request

{
  "follow": {
    "followee_id": <bigint>
  }
}

Response

{
  "follower_id": <bigint>
  "followee_id": <bigint>
}

GET /users/:username/subscriptions

Gets the Users the User is following.

Response

{
  "id": <bigint>
  "display_name": <string>
  "username": <string>
  "followed_users": [
    {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
      "following_current_user": <boolean>
      "current_user_following": <boolean>
    }
    ...
  ]
}

GET /users/:username/followers

Gets the Users that follow the User.

Response

{
  "id": <bigint>
  "display_name": <string>
  "username": <string>
  "followers": [
    {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
      "following_current_user": <boolean>
      "current_user_following": <boolean>
    }
    ...
  ]
}

Search

GET /search/quick

Does a quick search of the top 6 most popular/active Users with the search text in their username or display_name.

Request

{
  "search": {
    "text": <string>
  }
}

Response

{
  "users": [
    {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
      "current_user_following": <boolean>
      "following_current_user": <boolean>
      "follower_count": <int>
      "followed_user_count": <int>
      "user_rating": <int>
    }
    ...
  ]
}

GET /search/top

Does a search of the top 3 most popular/active Users with the search text in their username or display_name and top 3 popular Posts and Comments with the search text in their text.

Request

{
  "search": {
    "text": <string>
  }
}

Response

{
  "users": [
    {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
      "current_user_following": <boolean>
      "following_current_user": <boolean>
      "follower_count": <int>
      "followed_user_count": <int>
      "user_rating": <int>
    }
    ...
  ]
  "posts": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "post_type": "Post"
      "like_count": <int>
      "repost_count": <int>
      "comment_count": <int>
      "post_date": <datetime>
      "user_liked": <boolean>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "rating": <int>
      "replying_to": null
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
  "comments": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "post_type": "Comment"
      "like_count": <int>
      "repost_count": <int>
      "comment_count": <int>
      "post_date": <datetime>
      "user_liked": <boolean>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "rating": <int>
      "replying_to": <string[]>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

GET /search/users

Does a search of the Users with the search text in their username or display_name.

Request

{
  "search": {
    "text": <string>
  }
}

Response

{
  "users": [
    {
      "id": <bigint>
      "username": <string>
      "display_name": <string>
      "current_user_following": <boolean>
      "following_current_user": <boolean>
      "follower_count": <int>
      "followed_user_count": <int>
      "user_rating": <int>
    }
    ...
  ]
}

GET /search/posts

Does a search of the Posts with the search text in their text.

Request

{
  "search": {
    "text": <string>
  }
}

Response

{
  "posts": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "post_type": "Post"
      "like_count": <int>
      "repost_count": <int>
      "comment_count": <int>
      "post_date": <datetime>
      "user_liked": <boolean>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "rating": <int>
      "replying_to": null
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

GET /search/comments

Does a search of the Comments with the search text in their text.

Request

{
  "search": {
    "text": <string>
  }
}

Response

{
  "comments": [
    {
      "id": <bigint>
      "text": <string>
      "created_at": <datetime>
      "post_type": "Comment"
      "like_count": <int>
      "repost_count": <int>
      "comment_count": <int>
      "post_date": <datetime>
      "user_liked": <boolean>
      "user_reposted": <boolean>
      "user_followed": <boolean>
      "rating": <int>
      "replying_to": <string[]>
      "author": {
        "id": <bigint>
        "username": <string>
        "display_name": <string>
      }
    }
    ...
  ]
}

About


Languages

Language:Ruby 99.9%Language:HTML 0.1%Language:Procfile 0.0%