## EAP
### A7: Web Resources Specification
The web application architecture that has to be developed is described, along with a list of resources and their attributes, such as graphical interface references and response formats in JSON. The following operations over data are available on this page: generate, view, amend, and remove
### 1. Overview
Identify and overview the modules that will be part of the application.
|Module| Description|
|---|---|
| M01: Static Pages| Website pages connected with static information such as about us page and home page|
| M02 : Authentication|Web resources with user authentication,includes register,login,logout and password recovery |
| M03 :Authenticated User Area|Web resources related to managing and customizing the user's personal area and deleting the account.|
| M04 : Project Area|The project area holds all project-related information and is responsible for searching the tasks.|
|M05 : Task Area|The task area holds all task-related information and comments.|
|M05 : Admin Pages |Web resources associated with the administrator capabilities of the organization include user and project management.|
### 2. Permissions
Define the permissions used by each module, necessary to access its data and features.
| Identifier| Name|Description |
|---|---|---|
|Pub| Public | Users without privileges|
| OWN|Owner | The owner of the content like project,task or comment|
|USR|User | Authenticated users|
| PM|Project Member | Member of a project|
| PL|Project Leader | Leader of a project|
|ADM|Admin |System administrator |
### 3. OpenAPI Specification
OpenAPI specification in YAML format to describe the vertical prototype's web resources.
[Link to a7_openapi.yaml file](https://git.fe.up.pt/lbaw/lbaw2324/lbaw2373/-/blob/main/EAP/a7_openapi.yaml?ref_type=heads&plain=0)
```yaml openapi: 3.0.0
openapi: 3.0.0
info:
version: '1.0'
title: 'LBAW Project TaskSquad'
description: 'Web Resources Specification (A7) for TaskSquad'
servers:
- url: http://lbaw2373.lbaw.fe.up.pt
description: Production server
tags:
- name: 'M01: Static Pages'
- name: 'M02: Authentication'
- name: 'M03: Authenticated User Area'
- name: 'M04: Project Area'
- name: 'M05: Task Area'
- name: 'M06: Admin Pages'
paths:
#-------------------------------- M01 -----------------------------------------
/:
get:
operationId: R101
summary: 'R101: Home Page'
description: 'See the home page when you access the app. Access: PUB'
tags:
- 'M01: Static Pages'
responses:
'200':
description: 'Ok. Show homepage'
/about-us/:
get:
operationId: R102
summary: 'R102: About Us'
description: 'Provide description about website and its creators. Access: PUB'
tags:
- 'M01: Static Pages'
responses:
'200':
description: 'Ok. Show About Us page'
/404:
get:
operationId: R103
summary: "R103: Not Found Page"
description: "Show TaskSquad Not Found page. Access: PUB"
tags:
- 'M01: Static Pages'
responses:
"404":
description: "Page not available"
#-------------------------------- M02 -----------------------------------------
/login:
get:
operationId: R201
summary: 'R201: Login Form'
description: 'Provide login form. Access: PUB'
tags:
- 'M02: Authentication'
responses:
'200':
description: 'Ok. Show log-in UI'
post:
operationId: R202
summary: 'R202: Login Action'
description: 'Processes the login form submission. Access: PUB'
tags:
- 'M02: Authentication'
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
email:
type: string
password:
type: string
required:
- email
- password
responses:
'302':
description: 'Redirect after processing the login credentials.'
headers:
Location:
schema:
type: string
examples:
302Success:
description: 'Successful authentication. Redirect to projects page.'
value: '/projects'
302Error:
description: 'Failed authentication. Redirect to login form.'
value: '/login'
/register:
get:
operationId: R203
summary: 'R203: Register Form'
description: 'Provide new user registration form. Access: PUB'
tags:
- 'M02: Authentication'
responses:
'200':
description: 'Ok. Show sign-up UI'
post:
operationId: R204
summary: 'R204: Register Action'
description: 'Processes the new user registration form submission. Access: PUB'
tags:
- 'M02: Authentication'
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
name:
type: string
email:
type: string
password:
type: string
required:
- name
- email
- password
responses:
'302':
description: 'Redirect after processing the new user information.'
headers:
Location:
schema:
type: string
examples:
302Success:
description: 'Successful authentication. Redirect to the projects page.'
value: '/projects'
302Failure:
description: 'Failed authentication. Redirect to register form.'
value: '/register'
/password-recovery:
get:
operationId: R205
summary: 'R205: Password Recovery Form'
description: 'Provide password recovery form. Access: PUB'
tags:
- 'M02: Authentication'
responses:
'200':
description: 'Ok. Show password recovery form'
put:
operationId: R206
summary: "R206: Change User's Password Form"
description: 'Show the Password Change Form. Access: OWN'
tags:
- 'M02: Authentication'
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
password:
type: string
responses:
'302':
description: 'Redirect after processing password recovery request'
headers:
Location:
schema:
type: string
examples:
302Success:
description: 'Ok. Redirect to login.'
value: '/login'
302Error:
description: 'Failed password recovery. Redirect to password recovery.'
value: '/password-recovery'
/logout:
post:
operationId: R207
summary: 'R207: Logout Action'
description: 'Logout the current authenticated used. Access: USR, ADM'
tags:
- 'M02: Authentication'
responses:
'302':
description: 'Redirect after processing logout.'
headers:
Location:
schema:
type: string
examples:
302Success:
description: 'Successful logout. Redirect to login form.'
value: '/login'
# ---------------------------- M03 -----------------------------------------------
/profile/{username}:
parameters:
- in: path
name: username
schema:
type: string
required: true
get:
operationId: R301
summary: 'R301: View User Profile Page'
description: 'Show the profile page . Access: USR'
tags:
- 'M03: Authenticated User Area'
parameters:
- in: path
name: username
schema:
type: string
required: true
responses:
'200':
description: 'Ok. Show profile page'
'404':
description: 'Profile not found'
delete:
operationId: R302
summary: "R302: Delete User Profile"
description: "Delete User account. Access: OWN"
tags:
- 'M03: Authenticated User Area'
responses:
'200':
description: 'Ok. Account deleted'
/profile/{username}/edit:
parameters:
- in: path
name: username
schema:
type: string
required: true
get:
operationId: R303
summary: 'R303: Edit User Profile Form'
description: 'Show the individual user profile edit form. Access: OWN'
tags:
- 'M03: Authenticated User Area'
parameters:
- in: path
name: username
schema:
type: integer
required: true
responses:
'200':
description: 'Ok. Show edit profile UI'
put:
operationId: R304
summary: 'R304: Edit User Profile Action'
description: 'Edit User Profile. Access: OWN'
tags:
- 'M03: Authenticated User Area'
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
username:
type: string
email:
type: string
name:
type: string
birthdate:
type: integer
profile_pic:
type: string
responses:
'302':
description: 'Redirect after processing the new user information.'
headers:
Location:
schema:
type: string
examples:
302Success:
description: 'Information successfully processed. Redirect to user profile.'
value: '/profile/{username}'
302Failure:
description: 'Failed to process information. Redirect to edit user information form.'
value: '/profile/{username}/edit'
/api/search/{query}:
parameters:
- in: path
name: query
schema:
type: string
required: true
get:
operationId: R305
summary: "R305: Search"
description: "Show Search hits page. Access: PUB"
tags:
- 'M03: Authenticated User Area'
parameters:
- in: query
name: query
description: 'Queried String'
schema:
type: string
required: true
responses:
"200":
description: "Ok. Show search page"
#-------------------------------- M04 -----------------------------------------
/create-project:
get:
operationId: R401
summary: 'R401: Create New Project Form'
description: 'Create New Project. Access: USR'
tags:
- 'M04: Project Area'
responses:
'200':
description: 'Ok. Show Create Project UI'
post:
operationId: R402
summary: 'R402: Create New Project Action'
description: 'Create New Project. Access: USR'
tags:
- 'M04: Project Area'
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
title:
type: string
description:
type: string
theme:
type: string
responses:
'302':
description: 'Redirect after processing the project information.'
headers:
Location:
schema:
type: string
examples:
302Success:
description: 'Success. Redirect to project area.'
value: '/project/{id}'
302Error:
description: 'Failed. Redirect to project creation form.'
value: '/create-project'
/project/{id}:
parameters:
- in: path
name: id
schema:
type: integer
required: true
get:
operationId: R403
summary: "R403: See project page"
description: "See the project page and all its information. Access: PM"
tags:
- 'M04: Project Area'
parameters:
- in: path
name: id
schema:
type: integer
required: true
responses:
'200':
description: 'Ok. Show project page UI'
delete:
operationId: R404
summary: "R404: Delete Project"
description: "Delete a Project. Access: PL"
tags:
- 'M04: Project Area'
parameters:
- in: path
name: id
schema:
type: integer
required: true
responses:
'200':
description: 'Project deleted'
/project/{id}/edit:
parameters:
- in: path
name: id
schema:
type: integer
required: true
get:
operationId: R405
summary: 'R405: Edit Project Form'
description: 'Show the project edit form. Access: OWN'
tags:
- 'M04: Project Area'
responses:
'200':
description: 'Ok. Show edit project UI'
put:
operationId: R406
summary: 'R406: Edit Project Action'
description: 'Edit Project. Access: OWN'
tags:
- 'M04: Project Area'
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
title:
type: string
description:
type: string
theme:
type: string
responses:
'302':
description: 'Redirect after processing the new project information.'
headers:
Location:
schema:
type: string
examples:
302Success:
description: 'Information successfully processed. Redirect to project page.'
value: '/project/{id}'
302Failure:
description: 'Failed to process information. Redirect to edit project form.'
value: '/project/{id}/edit'
/api/{project_id}/search/{query}:
parameters:
- in: path
name: project_id
schema:
type: integer
required: true
- in: path
name: query
schema:
type: string
required: true
get:
operationId: R407
summary: 'R407: Search Tasks API'
description: 'Search for tasks and return the results as JSON. Access: PM.'
tags:
- 'M04: Project Area'
parameters:
- in: query
name: query
description: 'String to use for full-text search'
schema:
type: string
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Task'
#-------------------------------- M05 -----------------------------------------
/{project_id}/task:
parameters:
- in: path
name: project_id
schema:
type: integer
required: true
post:
operationId: R501
summary: "R501: Create new task"
description: "Create a new task. Access: PM"
tags:
- 'M05: Task Area'
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
task-name:
type: string
task-description:
type: string
task-members:
type: array
items:
$ref: '#/components/schemas/Task'
dead-line:
type: string
items:
$ref: '#/components/schemas/User'
due-date:
type: string
responses:
'200':
description: 'Task Created'
/{project_id}/task/{task_id}:
parameters:
- in: path
name: project_id
schema:
type: integer
required: true
- in: path
name: task_id
schema:
type: integer
required: true
get:
operationId: R502
summary: "R502: Get task info"
description: "Get the task's information. Access: PM"
tags:
- 'M05: Task Area'
responses:
'200':
description: 'Ok. Show task page UI'
delete:
operationId: R503
summary: "R503: Delete task"
description: "Delete a task. Access: OWN"
tags:
- 'M05: Task Area'
responses:
'200':
description: 'Task deleted'
/{project_id}/task/{task_id}/edit:
parameters:
- in: path
name: project_id
schema:
type: integer
required: true
- in: path
name: task_id
schema:
type: integer
required: true
get:
operationId: R504
summary: "R504: Edit Task Form"
description: "Get the edit task form. Access: OWN"
tags:
- 'M05: Task Area'
responses:
'200':
description: 'Ok. Show edit task page UI'
put:
operationId: R505
summary: "R505: Update task info"
description: "Update the task's information. Access: OWN"
tags:
- 'M05: Task Area'
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
priority:
type: string
content:
type: string
is_completed:
type: boolean
date_creation:
type: integer
deadline:
type: integer
title:
type: string
id_project:
type: array
items:
$ref: '#/components/schemas/Project'
responses:
'302':
description: 'Redirect after processing the new task information.'
headers:
Location:
schema:
type: string
examples:
302Success:
description: 'Information successfully processed. Redirect to task page.'
value: '/{project_id}/task/{task_id}'
302Failure:
description: 'Failed to process information. Redirect to edit task form.'
value: '/{project_id}/task/{task_id}/edit'
/api/{task_id}/comments:
parameters:
- in: path
name: task_id
schema:
type: integer
required: true
post:
operationId: R506
summary: "R506: Create a Comment for a Task"
description: "Create a comment for a task. Access: PM"
tags:
- 'M05: Task Area'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
text:
type: string
responses:
'200':
description: 'Comment created'
/api/{comment_id}:
parameters:
- in: path
name: comment_id
schema:
type: integer
required: true
put:
operationId: R507
summary: "R507: Edit a Comment for a Task"
description: "Edit a comment for a task. Access: PM"
tags:
- 'M05: Task Area'
parameters:
- in: path
name: comment_id
schema:
type: integer
required: true
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
text:
type: string
responses:
'200':
description: 'Comment updated'
delete:
operationId: R508
summary: "R508: Delete a Comment for a Task"
description: "Delete a comment for a task. Access: PM"
tags:
- 'M05: Task Area'
parameters:
- in: path
name: comment_id
schema:
type: integer
required: true
responses:
'200':
description: 'Comment deleted'
#-------------------------------- M06 -----------------------------------------
/admin:
get:
operationId: R601
summary: "R601: Admin Pages"
description: "Show administrator page. Access: ADM"
tags:
- "M06: Admin Pages"
responses:
"302":
description: "Ok. Show admin UI"
"404":
description: "Page not available"
/admin/browse/users:
get:
operationId: R602
summary: 'R602: Browse Users API'
description: 'Show Browse Users page. Access: ADM.'
tags:
- 'M06: Admin Pages'
responses:
'200':
description: 'Success'
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
/admin/browse/projects:
get:
operationId: R603
summary: 'R603: Browse Projects API'
description: 'Show Browse Projects page. Access: ADM.'
tags:
- 'M06: Admin Pages'
responses:
'200':
description: 'Success'
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Project'
# -------------------- Components --------------------
components:
schemas:
User:
type: object
properties:
id:
type: integer
username:
type: string
password:
type: string
email:
type: string
Generic_User:
type: object
properties:
id:
type: integer
name:
type: string
birthdate:
type: integer
profile_pic:
type: string
isBanned:
type: boolean
Project:
type: object
properties:
id:
type: integer
title:
type: string
description:
type: string
theme:
type: string
archived:
type: boolean
Task:
type: object
properties:
id:
type: integer
priority:
type: string
content:
type: string
is_completed:
type: boolean
date_creation:
type: integer
deadline:
type: integer
title:
type: string
id_project:
type: array
items:
$ref: '#/components/schemas/Project'
Comment:
type: object
properties:
id:
type: integer
content:
type: string
date:
type: integer
Likes:
type: object
properties:
id:
type: integer
comment_id:
type: array
items:
$ref: '#/components/schemas/Comment'
generic_user_id:
type: array
items:
$ref: '#/components/schemas/Generic_User'
Is_Admin:
type: object
properties:
id:
type: integer
user_id:
type: array
items:
$ref: '#/components/schemas/User'
Favorite:
type: object
properties:
id:
type: integer
project_id:
type: array
items:
$ref: '#/components/schemas/Project'
generic_user_id:
type: array
items:
$ref: '#/components/schemas/Generic_User'
Notification:
type: object
properties:
id:
type: integer
description:
type: string
Project_Notification:
type: object
properties:
id:
type: integer
project_id:
type: array
items:
$ref: '#/components/schemas/Project'
notification_id:
type: array
items:
$ref: '#/components/schemas/Notification'
user_id:
type: array
items:
$ref: '#/components/schemas/User'
project_type:
type: string
Task_Notification:
type: object
properties:
id:
type: integer
task_id:
type: array
items:
$ref: '#/components/schemas/Task'
notification_id:
type: array
items:
$ref: '#/components/schemas/Notification'
user_id:
type: array
items:
$ref: '#/components/schemas/User'
task_type:
type: string
Comment_Notification:
type: object
properties:
id:
type: integer
comment_id:
type: array
items:
$ref: '#/components/schemas/Comment'
notification_id:
type: array
items:
$ref: '#/components/schemas/Notification'
user_id:
type: array
items:
$ref: '#/components/schemas/User'
comment:
type: string
Is_Member:
type: object
properties:
id_user:
type: array
items:
$ref: '#/components/schemas/User'
id_project:
type: array
items:
$ref: '#/components/schemas/Project'
Is_Leader:
type: object
properties:
id_user:
type: array
items:
$ref: '#/components/schemas/User'
id_project:
type: array
items:
$ref: '#/components/schemas/Project'
Task_Owner:
type: object
properties:
id_user:
type: array
items:
$ref: '#/components/schemas/User'
id_task:
type: array
items:
$ref: '#/components/schemas/Task'
Assigned:
type: object
properties:
id_user:
type: array
items:
$ref: '#/components/schemas/User'
id_task:
type: array
items:
$ref: '#/components/schemas/Task'
Comment_Owner:
type: object
properties:
id_user:
type: array
items:
$ref: '#/components/schemas/User'
id_comment:
type: array
items:
$ref: '#/components/schemas/Comment'
```
### A8: Vertical prototype
The Vertical Prototype is where the most significant user stories are implemented. It is also used to familiarize users with the project's technology and validate the provided architecture. During the implementation phase, the user interface, business logic, and data access layers of the solution's architecture are all being worked on using the LBAW Framework. The prototype covers various functionalities, including information visualization pages' execution, information entry, editing, and removal, permission control for accessing the implemented pages, and error and success messages display.
### 1. Implemented Features
#### 1.1. Implemented User Stories
The preceding section illustrates the user stories that have been integrated into the prototype.
User Story reference | Name|Priority| Description|
| ----------- | -------------------------------------------------------|-----------|---------|
|US01| Sign-in | High |As a Visitor, I want to authenticate into the system, so that I can access privileged information|
|US02| Sign-up | High |As a Visitor, I want to register myself into the system, so that I can authenticate myself into the system|
|US12| Home | High | As a User, I want to access the home page, so that I can see a brief presentation of the website |
|US21| Create Project | High | Authenticated User can create a Project |
|US22| View My Projects | High | As an authenticated user can see all my projects, whether I'm a member or a leader |
|US24| View Profile | High | As an authenticated user, I can see my profile whenever I want |
|US25| Edit Profile | High | As an authenticated user, I can edit my profile whenever I want |
|US41| Create Task | High | As a project member can create a task |
|US42| Manage Task | High | As a project member you can assign a property to a task |
|US43| View Task Details | High | A member can see all the details of tasks with priority or content |
|US44| Complete an Assigned Task | High | As a project member you can complete the task assigned to you|
|US45| Search Tasks | High | As member from the project can search for any tasks of the project |
|US46| Assign Users to Tasks | High | As a project member can assign a task to a person |
|US48| Assigned to Task | High | If you're assigned a task to do, you'll receive a notification about it |
|US51| Add user to Project | High | As a project leader you can add several users to your project |
#### 1.2. Implemented Web Resources
The subsequent section outlines the web resources integrated into the prototype.
##### Module M01: Static Pages
|Web Resource Reference|URL|
|-----|-----|
|R101: Home Page| GET /home |
##### Module M02: Authentication
|Web Resource Reference|URL|
|-----|-----|
|R201: Login Form| GET /login|
|R202: Login Action| POST /login|
|R203: Register Form| GET /register|
|R204: Register Action| POST /register|
|R207: Logout Action| POST /logout|
##### Module M03: Authenticated User Area
|Web Resource Reference|URL|
|-----|-----|
|R301: View User Profile Page| GET /profile/{id}|
|R302: Edit User Profile Form| GET /profile/{id}/edit|
|R303: Edit User Profile Action| PUT /profile/{id}/edit|
|R304: Search users or project| GET /search/users|
##### Module M04: Project Area
|Web Resource Reference|URL|
|-----|-----|
|R401: Create New Project Form| GET /create-project|
|R402: Create New Project Action| POST /projects|
|R403: See Project Page| GET /project/{title} |
|R404: See My Projects | GET /myProjects |
|R405: AddMember Form| GET /project/{title}/addMember |
|R406: AddMember Action| POST /project/{title}/addMember/store |
|R407: AddLeader Form| GET /project/{title}/addLeader |
|R408: AddLeader Action| POST /project/{title}/addLeader/store |
|R409: Pending Invites from the Leader| GET /pending-invites |
|R410: Accept Invite| POST /accept-invite/{id_user}/{id_project} |
|R411: Decline Invite| POST /decline-invite/{id_user}/{id_project}|
|R412: Show Members| GET /project/{title}/members |
|R413: Show Leaders| GET /project/{title}/leaders |
##### Module M05: Task Area
|Web Resource Reference|URL|
|-----|-----|
|R501: Create New Task Form| GET /project/{title}/createTask|
|R502: Create New Task Action| POST /project/{title}/storeTask|
|R503: See and search tasks| GET /project/{title}/task|
|R504: Mark as Completed| PATCH /project/{title}/task/{taskId}/complete|
##### Module M06: Admin Area
|Web Resource Reference|URL|
|-----|-----|
|R601: Admin Pages| GET /admin|
#### 2. Prototype
The prototype is available at [here](https://lbaw2373.lbaw.fe.up.pt)
Credentials:
* admin user:
* email: bob@example.com
* password:1234
* regular user:
* email:david@lbaw.com
* password:1234
* email:alice@example.com
* password:1234
The code is available [here](https://git.fe.up.pt/lbaw/lbaw2324/lbaw2373).
Revision history
Changes made to the first submission:
Item 1
..
GROUP2373, 20/11/2023
David dos Santos Ferreira , up202006302@fc.up.pt (Editor)
Ana Sofia Oliveira Teixeira , up201806629@fe.up.pt
Ana Sofia Silva Pinto , up202004606@fc.up.pt
Gabriela Dias Salazar Neto Silva , up202004443@fe.up.pt