-
Notifications
You must be signed in to change notification settings - Fork 1
EAP Architecture Specification and Prototype
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.
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) |
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 |
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}'
Brief presentation of the artefact goals.
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 |
Web Resource Reference | URL |
---|---|
Login Form | GET /login |
Login Action | POST /login |
Register Form | GET /register |
Register Action | POST /register |
Logout Action | POST /logout |
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} |
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}' |
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} |
Web Resource Reference | URL |
---|---|
About Page | GET /tags |
FAQ Page | GET /tag/{tagId} |
Web Resource Reference | URL |
---|---|
User Profile | GET /user/{username} |
Get Edit Profile page | GET /user/{username}/edit |
Update User Profile | POST /user/{username} |
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} |
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
Changes made to the first submission:
No changes were made yet.
GROUP2153, 30/11/2021
- Fabio Huang, up201806829@g.uporto.pt
- Ivo Ribeiro, up201307718@g.uporto.pt
- Pedro Pacheco, up201806824@g.uporto.pt
- Vasco Soares Nogueira Garcia, up201805255@g.uporto.pt