Skip to content

EAP Architecture Specification and Prototype

Fab Huang edited this page Jul 22, 2022 · 1 revision

A7: Web Resources Specification

The architecture of the web application is presented here with all the resources, their respecive properties and the format of JSON responses.
This specification adheres to the OpenAPI standard using YAML.

1. Overview

Modules that will be part of the application.

M01: Authentication Web resources associated with user authentication. Includes the following system features: login/logout, registration, credential recovery.
M02: Questions Web resources associated with questions that are posted. This includes the following system features: viewing/browsing a specific question and its answers, searching by title, filtering by tags. Authenticated users can also edit/create their own questions and answers previously posted
M03: Static Pages Web resources associated with static content. This includes the following system features: about us, contacts, services, etc...
M04: Administration Web resources associated with user administration (block, delete account ) and forum's moderators (edit question's tags, delete questions, answers or comments)
M05: Users Web resources associated with individual user profile management. This includes the following system features: edit user profile (fullname, bio, status...), overview of posted content, edit/delete posted contents (questions, answers and comments)

2. Permissions

This table presents permission levels to establish users access to the resources

VIS Visitor Non Authenticated Users
BAN Banned User banned from the website
USR User Authenticated Users
OWN Owner Content Owner (eg. own profile, own questions)
MOD Moderator Content Moderator
ADM Administrator Website's Admin

3. OpenAPI Specification

OpenAPI specification in YAML format to describe the web application's web resources. Link to the a7_openapi.yaml file in the group's repository. openapi: 3.0.0

openapi: 3.0.0

info:
  version: '1.0'
  title: 'iNeedHelp Web API'
  description: 'Web Resources Specification for iNeedHelp'

servers:
- url: http://lbaw.fe.up.pt # Alterar !!
  description: Production server

externalDocs:
  description: Our Project Documentation
  url: https://git.fe.up.pt/lbaw/lbaw2122/lbaw2153/-/wikis/home

tags:
  - name: 'M01: Authentication'
  - name: 'M02: Questions'
  - name: 'M03: Static Pages'
  - name: 'M04: Administration'
  - name: 'M05: Answers'
  - name: 'M06: Users'
  - name: 'M07: Comments'

paths:
  # M01: Authentication
  /login:
    get:
      operationId: R101
      summary: 'R101: Login Form'
      description: 'Provides the login form. ACCESS: VIS'
      tags:
        - 'M01: Authentication'
      responses:
        '200':
          description: 'OK. Show login UI'

    post:
      operationId: R102
      summary: 'R102: Login Action'
      description: 'Processes login form submission. ACCESS: VIS'
      tags:
        - 'M01: Authentication'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                identifier: # which can be either username or email
                  type: string
                password:
                  type: string
              required:
                - identifier
                - password
      responses:
        '302':
          description: 'Redirect after processing the login credentials'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful authentication. Redirect to home page'
                  value: '/' 
                302Error:
                  description: 'Failed authentication. Redirect to login form.'
                  value: '/login'

  /logout:
    post:
      operationId: R103
      summary: 'R103: Logout Action'
      description: 'Logout the current authenticated user. ACCESS: USR, MOD, ADM'
      tags:
        - 'M01: Authentication'
      responses:
        '302':
         description: 'Redirect after processing logout.'
         headers:
           Location:
             schema:
               type: string
             examples:
               302Success:
                 description: 'Successful logout. Redirect to login form.'
                 value: '/login'

  /register:
    get:
      operationId: R104
      summary: 'R104: Register Form'
      description: 'Provides the registration form. ACCESS: VIS'
      tags:
        - 'M01: Authentication'
      responses:
        '200':
         description: 'Ok. Show Sign-Up Interface'   
    
    post:
      operationId: R105
      summary: 'R105: Register Action'
      description: 'Processes registration form submission. ACCESS: VIS'
      tags:
        - 'M01: Authentication'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                full_name:
                  type: string
                email:
                  type: string
                password:
                  type: string
              required:
                - username
                - email
                - password
      responses:
        '302':
          description: 'Redirect after processing the new user information.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful authentication. Redirect to user profile.'
                  value: '/users/{id}'
                302Failure:
                  description: 'Failed authentication. Redirect to register form.'
                  value: '/register'

  # M06: Users
  /users/{id}:
    get:
      operationId: R601
      summary: 'R601: User Profile Page'
      description: 'Shows authenticated user profile page. ACCESS: VIS'
      tags:
        - 'M06: Users'
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        '200':
          description: 'OK. Show user profile page.'
  
    put: #edit user profile information
      operationId: R602
      summary: 'R602: Edit User Profile Action'
      description: 'Processes the new user profile information from form submission. ACCESS: OWN, ADM'
      tags:
        - 'M06: Users'
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                bio:
                  type: string
                location:
                  type: string
                email:
                  type: string
                password:
                  type: string
                profile_image:
                  type: string
                  format: binary
                full_name: 
                  type: string
                status:
                  type: string
      responses:
        '302':
          description: 'Redirect after processing the new user information.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful profile edition submission. Redirect to user profile.'
                  value: '/users/{id}'
                302Failure:
                  description: 'Failed profile edition submission. Redirect to user profile.'
                  value: '/users/{id}'

  # M02: Questions
  /api/questions:
    get:
      operationId: R201
      summary: 'R201: Search Question API'
      description: 'Searches for questions and returns the results as JSON. Access: VIS'
      tags:
        - 'M02: Questions'
      parameters:
       - in: query
         name: query
         description: String to use for full-text search
         schema:
           type: string
         required: false
       - in: query
         name: tags
         description: Tags of the questions
         schema:
           type: string
         required: false
       - in: query
         name: keywords
         description: Keywords that might be found in the content body of the question
         schema:
           type: string
         required: false
       - in: query
         name: author
         description: The username of the author who post the question
         schema:
           type: integer
         required: false
       - in: query
         name: min_views
         description: Minimal number of views
         schema:
           type: integer
         required: false
       - in: query
         name: max_views
         description: Maximal number of views
         schema:
           type: integer
         required: false
       - in: query
         name: min_created_at
         description: Minimal created time
         schema:
           type: string
         required: false
       - in: query
         name: max_created_at
         description: Maximal created time
         schema:
           type: string
         required: false
       - in: query
         name: min_updated_at
         description: Minimal updated time
         schema:
           type: string
         required: false
       - in: query
         name: max_updated_at
         description: Max updated time
         schema:
           type: string
         required: false
       - in: query
         name: result_size
         description: Number of results that will be returned. By default 10.
         schema:
           type: integer
         required: false
      responses:
        '200':
          description: 'Success'
          content:
           application/json:
             schema:
               type: array
               items:
                 type: object
                 properties:
                   id:
                     type: string
                   title:
                     type: string
                   content:
                     type: string
                   views:
                     type: integer
                   user_id:     # The author of the question
                     type: integer
                   created_at:
                     type: object
                   updated_at:
                     type: object
                   tags:
                     type: string
                   answers:
                     type: array    #Array of answer id
                   accepted_answer_id: 
                     type: integer
               example:
                 result: {
                   id: 1,
                   title: "Who is Linus Torvalds?",
                   content: "I would like to know who Linus Torvalds is, and what has he done?",
                   views: 9192,
                   user_id: 1,
                   created_at: 12 December 2021,
                   updated_at: 13 December 2021,
                   tags: "linux, people",
                   accepted_answer_id: 1,
                   answers: {
                    answerid: 1,
                    content: "He was the person who invented linux",
                    user_id: 2,
                    created_at: 13 December 2021,
                    updated_at: 13 December 2021,
                  }
                 }


  /questions/{id}:
    get:
      operationId: R202
      summary: 'R202: Question Page'
      description: 'Shows individual question page. ACCESS: VIS'
      tags:
        - 'M02: Questions'
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        '200':
          description: 'OK. Show individual question page.'
    delete:
      operationId: R203
      summary: 'R203: Delete Question Action'
      description: 'Processes the delete Question requesiton. ACCESS: OWN, ADM'
      tags:
        - 'M02: Questions'
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        '302':
          description: 'Redirect after deleting Question.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful question deletion. Redirect to home page.'
                  value: '/'
                302Failure:
                  description: 'Failed question deletion. Redirect to question page.'
                  value: '/questions/{id}'
    put:
      operationId: R204
      summary: 'R204: Edit Question Action'
      description: 'Processes the new question information from form submission. Access: OWN, ADM'
      tags:
        - 'M02: Questions'
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                content:
                  type: string
                tags:
                  type: string
      responses:
        '302':
          description: 'Redirect after Question edition form submission.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful question edition. Redirect to question page.'
                  value: '/questions/{id}'
                302Failure:
                  description: 'Failed question edition. Redirect to question page.'
                  value: '/questions/{id}'
  
  /questions/new:
    get:
      operationId: R205
      summary: 'R205: Question Form'
      description: 'Shows new question form. ACCESS: USR'
      tags:
        - 'M02: Questions'
      responses:
        '200':
          description: 'Ok. Show new question form'

    post:
      operationId: R206
      summary: 'R206: Question Form Action'
      description: 'Processes the new question form. ACCESS: USR'
      tags:
        - 'M02: Questions'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                content:
                  type: string
                tags: 
                  type: string 
              required:
                - title
                - content
                - tags
      responses:
        '302':
          description: 'Ok. Redirect to the newly created question page'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful question. Direct to new question page'
                  value: '/question/{id}' 
                302Error:
                  description: 'Failed question. Redirect to question form.'
                  value: '/question/new'
                  
  # M05: Answers
  /questions/{id}/answers/new:    
    post:
      operationId: R501
      summary: 'R501: Answer Form Action'
      description: 'Processes the new answer form. ACCESS: USR'
      tags:
        - 'M05: Answers'
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
              required:
                - content
      responses:
        '302':
          description: 'Ok. Redirect to the newly created question page'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful answer'
                  value: '/questions/{id}' 
                302Error:
                  description: 'Failed answer. Redirect to answer form.'
                  value: '/questions/{id}/answer/new'
  
  /questions/{question_id}/answers/{answer_id}:
    put:
      operationId: R502
      summary: 'R502: Edit Answer Action'
      description: 'Processes the new answer information from form submission. Access: OWN, ADM'
      tags:
        - 'M05: Answers'
      parameters:
        - in: path
          name: question_id
          schema:
            type: integer
          required: true
        - in: path
          name: answer_id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
      responses:
        '302':
          description: 'Redirect after question page.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful answer edition. Redirect to question page.'
                  value: 'questions/{question_id}'
                302Failure:
                  description: 'Failed asnwer edition. Redirect to question page.'
                  value: 'questions/{question_id}'
    delete:
      operationId: R503
      summary: 'R503: Delete Answer Action'
      description: 'Processes the delete Asnwer requesiton. ACCESS: OWN, ADM'
      tags:
        - 'M05: Answers'
      parameters:
        - in: path
          name: question_id
          schema:
            type: integer
          required: true
        - in: path
          name: answer_id
          schema:
            type: integer
          required: true
      responses:
        '302':
          description: 'Redirect after deleting Answer.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful answer deletion. Redirect to question page.'
                  value: 'questions/{question_id}'
                302Failure:
                  description: 'Failed answer deletion. Redirect to question page.'
                  value: 'questions/{question_id}'
        
  # M07: Comments
  /comment:
    post:
      operationId: R701
      summary: 'R701: Post new Comment Action'
      description: 'Processes new comment. ACCESS: USR'
      tags:
        - "M07: Comments"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string # Enum for QUESTION, ANSWER
                identifier:
                  type: integer # question id or answer id, depending on 'type'
                content:
                  type: string
              required:
                - type
                - identifier
                - content 
      responses:
        '302':
          description: 'Redirect after new comment.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful! New comment posted. Redirect to question page.'
                  value: 'questions/{id}'
                302Failure:
                  description: 'Failed to post new comment. Redirect to question page.'
                  value: 'questions/{id}'  

  /comment/{id}:     
    delete:
      operationId: R702
      summary: 'R702: Delete Comment Action'
      description: 'Deletes the comment, if the caller has permission. ACCESS: OWN, MOD, ADM'
      tags:
        - "M07: Comments"
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        '302':
          description: 'Redirect after comment deletion.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful! Comment was deleted. Redirect to question page.'
                  value: 'questions/{id}'
                302Failure:
                  description: 'Failed to delete comment. Redirect to question page.'
                  value: 'questions/{id}'  
      
    put:
      operationId: R703
      summary: 'R703: Edit Comment Action'
      description: 'Edits the comment, if the caller has permission. ACCESS:USR, ADM'
      tags:
        - "M07: Comments"
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
      responses:
        '302':
          description: 'Redirect after comment edition.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful! Comment was edited. Redirect to question page.'
                  value: 'questions/{id}'
                302Failure:
                  description: 'Failed to edit comment. Redirect to question page.'
                  value: 'questions/{id}'  
    
  # M03: Static Pages
  /about-us:
    get:
      operationId: R301
      summary: 'R301: About-Us Page'
      description: 'Shows about us page ACCESS: VIS'
      tags:
        - 'M03: Static Pages'
      responses:
        '200':
          description: 'Ok. Show about-us page'

  /support:
    get:
      operationId: R302
      summary: 'R302: Support Page'
      description: 'Shows support page ACCESS: VIS'
      tags:
        - 'M03: Static Pages'
      responses:
        '200':
          description: 'Ok. Show Support page'

  /authentication:
    get:
      operationId: R303
      summary: 'R303: Authentication Needed Page'
      description: 'Shows the authentication needed page. ACCESS: VIS'
      tags:
        - 'M03: Static Pages'
      responses:
        '200':
          description: 'Ok. Show authentication needed page'

  # M04: Administration
  /admin:
    get:
      operationId: R401
      summary: 'R401: Administration Dashboard Page'
      description: 'Shows the administration dashboard page. ACCESS: ADM'
      tags:
        - 'M04: Administration'
      responses:
        '200':
          description: 'Ok. Show dashboard page'
  /users/{id}/banned:
    put: 
      operationId: R402
      summary: 'R402: Bans an user'
      description: "Bans an user, by changing the user's is_block property. ACCESS: ADM, MOD"
      tags:
        - 'M04: Administration'
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        '302':
          description: 'Redirect after banning an user.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful! User was banned. Redirect to user profile.'
                  value: '/users/{id}'
                302Failure:
                  description: 'Failed to ban the user. Redirect to user profile.'
                  value: '/users/{id}'
  /users/{id}/unbanned:
    put: 
      operationId: R403
      summary: 'R403: Unbans an user'
      description: "Unbans an user, by changing the user's is_block property. ACCESS: ADM, MOD"
      tags:
        - 'M04: Administration'
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        '302':
          description: 'Redirect after unbanning an user.'
          headers:
            location:
              schema:
                type: string
              examples:
                302Success:
                  description: 'Successful! User was unbanned. Redirect to user profile.'
                  value: '/users/{id}'
                302Failure:
                  description: 'Failed to unban the user. Redirect to user profile.'
                  value: '/users/{id}'

A8: Vertical prototype

Brief presentation of the artefact goals.

1. Implemented Features

1.1. Implemented User Stories

The following user stories were implemented in the prototype:

Identifier Name Priority Description
US01 See Home Page High As a User, I want to see the home page, so that I can have an idea of what this website is about
US02 See About Page High As a User, I want to see the about page, so that I can find out a more detailed description of this website
US03 See Contact Page High As a User, I want to see the contact page, so that I can find solutions to issues that I may face during the usage of this website
US04 Browse/Read Without Sign-in high As a User, I want to quickly navigate and browse the system without being forced to register or login into the system so that I have the option to just quickly view the topic that interests me without wasting too much time
US05 Search by name high As a User, I want to quickly search for the content that I would like to know about (posts, questions, users) by name so that I do not need to waste time browsing each content one by one
US11 Sign-in high As a Visitor, I want to authenticate into the system, so that I can access privileged information (post questions and answer questions)
US12 Registration high As a Visitor, I want to register myself into the system, so that I can authenticate myself into the system and access further features
US22 Logout high As an Authenticated User I want to be able to do sign out from my account so that I can change to other accounts and also for safety reasons
US25 View Profile medium As an Authenticated User I want to access my user profile page so I can see all my data and activity
US26 Edit Profile medium As an Authenticated User I want to be able to edit my profile to my liking, including biography, profile picture, and also manage private information
US41 Edit Question high As an Author I want to be able to edit my questions/answers/comments
US42 Delete Question high As an Author I want to be able to delete my questions/answers/comments
US52 Mark Answer as Correct high As a Question Author I want to be able to mark an answer as correct
US51 Administrator Accounts high As an Administrator, I want an account that will able me to manage specific and overall features
US52 Administer User Accounts (search, view, edit, create) high As an Administrator, I want to manage all user accounts
US53 Block/Unblock User Accounts high As an Administrator, I want to block and unblock user accounts to control their access
US54 Delete User Account high As an Administrator, I want to delete user accounts, so that they are no longer visible

1.2. Implemented Web Resources

Authentication

Web Resource Reference URL
Login Form GET /login
Login Action POST /login
Register Form GET /register
Register Action POST /register
Logout Action POST /logout

Question

Web Resource Reference URL
Browse Questions List GET /questions
Browse A Specific Question GET /questions/{id}
New Question Form GET /new-question
New Question Action POST /new-question
Accept An Answer Action PATCH /questions/{questionId}/{answerId}
Unaccept An Answer Action DELETE /questions/{questionId}/{answerId}
Like On Question Action POST /questions/{questionID}/review/{type}
Dislike On Question Action DELETE /questions/{questionID}/review/{type}
Show Edit Question Form GET /questions/{questionId}/edit
Edit Question Action PATCH /questions/{questionId}
Follow a Question Action POST /questions/{questionId}

Answer

Web Resource Reference URL
New Answer Action POST /questions/{id}/answers/new
Like An Answer Action POST /answers/{answerId}/review/{type}
Dislike An Answer Action DELETE /answers/{answerId}/review/{type}
Delete An Answer Action DELETE /answers/{answerId}'
Edit An Answer Action PATCH /answers/{answerId}'

Comments

Web Resource Reference URL
Like Comment POST /comments/{commentId}/review/{type}'
Dislike Comment POST /comments/{commentId}/review/{type}'
New Comment DELETE /comments/new
Delete Comment DELETE /comments/{commentId}
Edit Comment PATCH /comments/{commentId}

Tags

Web Resource Reference URL
About Page GET /tags
FAQ Page GET /tag/{tagId}

User

Web Resource Reference URL
User Profile GET /user/{username}
Get Edit Profile page GET /user/{username}/edit
Update User Profile POST /user/{username}

Admin

Web Resource Reference URL
Admin Page GET /admin/{category}
Block/Unblock User POST /block/{userId}
Delete User DELETE /admin/users/{userId}
Delete Question DELETE /admin/questions/{questionId}
Delete Tag DELETE /admin/tags/{tagId}

2. Prototype

The prototype is available at http://lbaw2153.lbaw.fe.up.pt/

User Credentials:

Username: admin

Password: admin

The code is available at https://git.fe.up.pt/lbaw/lbaw2122/lbaw2153


Revision history

Changes made to the first submission:

No changes were made yet.


GROUP2153, 30/11/2021