Initial commit in this repository
This commit is contained in:
BIN
docs/design/Final Project ERD.jpeg
Normal file
BIN
docs/design/Final Project ERD.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 215 KiB |
BIN
docs/design/Phase_1-Design_Document.docx
Normal file
BIN
docs/design/Phase_1-Design_Document.docx
Normal file
Binary file not shown.
BIN
docs/design/Phase_1-Design_Document.pdf
Normal file
BIN
docs/design/Phase_1-Design_Document.pdf
Normal file
Binary file not shown.
BIN
docs/design/Phase_1-Design_PDF.xps
Normal file
BIN
docs/design/Phase_1-Design_PDF.xps
Normal file
Binary file not shown.
53
docs/design/Roadmap
Normal file
53
docs/design/Roadmap
Normal file
@@ -0,0 +1,53 @@
|
||||
# IDEA TRACKER API - DEVELOPMENT ROADMAP
|
||||
|
||||
# PHASE 1: MIDDLEWARE & VALIDATION
|
||||
|
||||
[x] Create authMiddleware.js - JWT verification and user authentication
|
||||
[x] Create validateIdeas.js - Request validation for idea endpoints - Validate POST: name (3+ chars), description (required) - Validate PUT: same as POST, but both optional - Validate param id as positive integer
|
||||
[x] Create validateProjects.js - Request validation for project endpoints - Validate POST: name (3+ chars), description (required) - Validate PUT: same as POST, but both optional - Validate param id as positive integer
|
||||
[x] Create validateMaterials.js - Request validation for material endpoints - Validate POST: projectId, name, description, source, author, text (all required) - Validate DELETE: param id as positive integer
|
||||
[x] Update/Review handleValidationErrors.js to ensure proper error responses
|
||||
|
||||
# PHASE 2: REPOSITORY LAYER (DATA ACCESS)
|
||||
|
||||
[x] Create ideasRepo.js - getAll(userId) - fetch all user ideas - getById(ideaId, userId) - fetch single idea with ownership check - create(userId, { name, description }) - update(ideaId, userId, { name, description }) - delete(ideaId, userId) - existsByName(userId, name) - check for duplicates
|
||||
[x] Create projectsRepo.js - getAll(userId) - getById(projectId, userId) - create(userId, { name, description }) - update(projectId, userId, { name, description }) - delete(projectId, userId) - existsByName(userId, name)
|
||||
[x] Create materialsRepo.js - getAll(userId) - all user materials - getByProjectId(projectId, userId) - materials for specific project - getById(materialId, userId) - single material with access check - create(userId, { projectId, name, description, source, author, text }) - delete(materialId, userId) - existsByName(userId, name)
|
||||
|
||||
# PHASE 3: SERVICE LAYER (BUSINESS LOGIC)
|
||||
|
||||
[x] Create ideasService.js - getAllIdeas(userId) - getIdeaById(ideaId, userId) - with 404 handling - createIdea(userId, { name, description }) - with duplicate check (409) - updateIdea(ideaId, userId, { name, description }) - with duplicate check - deleteIdea(ideaId, userId) - with 404 handling
|
||||
[x] Create projectsService.js - Same methods as ideas service
|
||||
[x] Create materialsService.js - getAllMaterials(userId) - getMaterialsByProject(projectId, userId) - createMaterial(userId, { projectId, name, description, source, author, text }) - deleteMaterial(materialId, userId) - Include project existence validation before creating material
|
||||
|
||||
# PHASE 4: CONTROLLER LAYER (REQUEST HANDLERS)
|
||||
|
||||
[x] Create ideasController.js - getAll(req, res) - GET /api/ideas - getById(req, res) - GET /api/ideas/:id - create(req, res) - POST /api/ideas - update(req, res) - PUT /api/ideas/:id - delete(req, res) - DELETE /api/ideas/:id
|
||||
[x] Create projectsController.js - getAll(req, res) - GET /api/projects - getById(req, res) - GET /api/projects/:id - create(req, res) - POST /api/projects - update(req, res) - PUT /api/projects/:id - delete(req, res) - DELETE /api/projects/:id
|
||||
[x] Create materialsController.js - getAll(req, res) - GET /api/materials - getByProject(req, res) - GET /api/materials/:projectId - create(req, res) - POST /api/materials - delete(req, res) - DELETE /api/materials/:id
|
||||
|
||||
# PHASE 5: ROUTES
|
||||
|
||||
[x] Create ideasRoutes.js - Route all endpoints with validation & auth middleware
|
||||
[x] Create projectsRoutes.js - Route all endpoints with validation & auth middleware
|
||||
[x] Create materialsRoutes.js - Route all endpoints with validation & auth middleware
|
||||
|
||||
# PHASE 6: UPDATE SERVER
|
||||
|
||||
[x] Update server.js - Replace /api/posts with /api/ideas - Add /api/projects routes - Add /api/materials routes
|
||||
|
||||
# PHASE 7: TESTING
|
||||
|
||||
[X] Test all endpoints with Swagger
|
||||
[X] Verify JWT auth on protected routes
|
||||
[x] Test 404, 409, 403 error cases
|
||||
[X] Run seed script: npm run seed
|
||||
[X] Verify Prettier formatting: npx prettier --write .
|
||||
|
||||
# PHASE 8: POLISH
|
||||
|
||||
[X] Write swagger for pagination
|
||||
[X] Write code for POST project Files (within projects layers)
|
||||
[X] Write code for DELETE project Files (within projects layers)
|
||||
[X] Edit swagger to show an option for "upload a file to this project"
|
||||
[X] create a path for downloading all files related to a project
|
||||
BIN
docs/design/Roadmap.docx
Normal file
BIN
docs/design/Roadmap.docx
Normal file
Binary file not shown.
699
docs/openapi.yaml
Normal file
699
docs/openapi.yaml
Normal file
@@ -0,0 +1,699 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Idea Tracker API
|
||||
version: 1.0.0
|
||||
description: A REST API for managing project ideas, projects, materials, and files
|
||||
servers:
|
||||
- url: http://localhost:8080
|
||||
description: Local development server
|
||||
|
||||
tags:
|
||||
- name: Authentication
|
||||
description: User authentication endpoints
|
||||
- name: Ideas
|
||||
description: Idea management endpoints
|
||||
- name: Projects
|
||||
description: Project management endpoints
|
||||
- name: Materials
|
||||
description: Project materials and resources
|
||||
|
||||
paths:
|
||||
/api/auth/signup:
|
||||
post:
|
||||
summary: Create a new user account
|
||||
tags:
|
||||
- Authentication
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SignupRequest'
|
||||
responses:
|
||||
'201':
|
||||
description: User created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserResponse'
|
||||
'400':
|
||||
description: Invalid input or validation error
|
||||
'409':
|
||||
description: Username already exists
|
||||
|
||||
/api/auth/login:
|
||||
post:
|
||||
summary: Login and receive JWT token
|
||||
tags:
|
||||
- Authentication
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LoginRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Login successful
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LoginResponse'
|
||||
'401':
|
||||
description: Invalid credentials
|
||||
|
||||
/api/ideas:
|
||||
get:
|
||||
summary: Get all ideas for the authenticated user
|
||||
tags:
|
||||
- Ideas
|
||||
security:
|
||||
- BearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Idea'
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
post:
|
||||
summary: Create a new idea
|
||||
tags:
|
||||
- Ideas
|
||||
security:
|
||||
- BearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/IdeaRequest'
|
||||
responses:
|
||||
'201':
|
||||
description: Idea created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Idea'
|
||||
'400':
|
||||
description: Bad Request - Validation error
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'409':
|
||||
description: Conflict - Idea with that name already exists
|
||||
|
||||
/api/ideas/{id}:
|
||||
put:
|
||||
summary: Update an idea
|
||||
tags:
|
||||
- Ideas
|
||||
security:
|
||||
- BearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/IdeaUpdateRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Idea updated successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Idea'
|
||||
'400':
|
||||
description: Bad Request - Id not a positive integer, or no fields provided
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'404':
|
||||
description: Not Found - No idea with that id belongs to this user
|
||||
'409':
|
||||
description: Conflict - Idea with that name already exists
|
||||
delete:
|
||||
summary: Delete an idea
|
||||
tags:
|
||||
- Ideas
|
||||
security:
|
||||
- BearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'204':
|
||||
description: Idea deleted successfully
|
||||
'400':
|
||||
description: Bad Request - Id not a positive integer
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'404':
|
||||
description: Not Found - No idea with that id belongs to this user
|
||||
|
||||
/api/projects:
|
||||
get:
|
||||
summary: Get all projects for the authenticated user
|
||||
tags:
|
||||
- Projects
|
||||
security:
|
||||
- BearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Project'
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
post:
|
||||
summary: Create a new project
|
||||
tags:
|
||||
- Projects
|
||||
security:
|
||||
- BearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ProjectRequest'
|
||||
responses:
|
||||
'201':
|
||||
description: Project created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Project'
|
||||
'400':
|
||||
description: Bad Request - Validation error
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'409':
|
||||
description: Conflict - Project with that name already exists
|
||||
|
||||
/api/projects/{id}:
|
||||
get:
|
||||
summary: Get a project by ID
|
||||
tags:
|
||||
- Projects
|
||||
security:
|
||||
- BearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Project'
|
||||
'400':
|
||||
description: Bad Request - Id not a positive integer
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'404':
|
||||
description: Not Found - No project with that id belongs to this user
|
||||
put:
|
||||
summary: Update a project
|
||||
tags:
|
||||
- Projects
|
||||
security:
|
||||
- BearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ProjectUpdateRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Project updated successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Project'
|
||||
'400':
|
||||
description: Bad Request - Id not a positive integer, or no fields provided
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'404':
|
||||
description: Not Found - No project with that id belongs to this user
|
||||
'409':
|
||||
description: Conflict - Project with that name already exists
|
||||
delete:
|
||||
summary: Delete a project
|
||||
tags:
|
||||
- Projects
|
||||
security:
|
||||
- BearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'204':
|
||||
description: Project deleted successfully
|
||||
'400':
|
||||
description: Bad Request - Id not a positive integer
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'404':
|
||||
description: Not Found - No project with that id belongs to this user
|
||||
|
||||
/api/projects/{id}/files:
|
||||
get:
|
||||
summary: List all files related to a project
|
||||
tags:
|
||||
- Projects
|
||||
security:
|
||||
- BearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/File'
|
||||
'400':
|
||||
description: Bad Request - Id not a positive integer
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'404':
|
||||
description: Not Found - No project with that id belongs to this user
|
||||
post:
|
||||
summary: Upload a file (Max 10MB)
|
||||
tags: [Projects]
|
||||
security: [{ BearerAuth: [] }]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/IdParam'
|
||||
requestBody:
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
type: string
|
||||
format: binary
|
||||
responses:
|
||||
'201':
|
||||
description: File uploaded
|
||||
'400':
|
||||
description: Bad Request - Id not a positive integer
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'404':
|
||||
description: Not Found - No project with that id belongs to this user
|
||||
'413':
|
||||
description: Payload Too Large - File size exceeds 10MB limit
|
||||
|
||||
/api/projects/files/{fileId}:
|
||||
delete:
|
||||
summary: Delete a specific project file
|
||||
tags: [Projects]
|
||||
security: [{ BearerAuth: [] }]
|
||||
parameters:
|
||||
- name: fileId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'204':
|
||||
description: File deleted
|
||||
'404':
|
||||
description: Not Found or Unauthorized
|
||||
|
||||
/api/projects/{id}/files/download:
|
||||
get:
|
||||
summary: Download all project files as a ZIP
|
||||
tags: [Projects]
|
||||
security: [{ BearerAuth: [] }]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/IdParam'
|
||||
responses:
|
||||
'200':
|
||||
description: A ZIP file containing all project documents
|
||||
content:
|
||||
application/zip:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
|
||||
/api/materials:
|
||||
get:
|
||||
summary: Get all materials for the authenticated user
|
||||
tags:
|
||||
- Materials
|
||||
security:
|
||||
- BearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Material'
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
post:
|
||||
summary: Create a new material
|
||||
tags:
|
||||
- Materials
|
||||
security:
|
||||
- BearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/MaterialRequest'
|
||||
responses:
|
||||
'201':
|
||||
description: Material created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Material'
|
||||
'400':
|
||||
description: Bad Request - Validation error
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'409':
|
||||
description: Conflict - Material with that name already exists
|
||||
|
||||
/api/materials/project/{projectId}:
|
||||
get:
|
||||
summary: Get all materials for a specific project
|
||||
tags:
|
||||
- Materials
|
||||
security:
|
||||
- BearerAuth: []
|
||||
parameters:
|
||||
- name: projectId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Material'
|
||||
'400':
|
||||
description: Bad Request - projectId not a positive integer
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
|
||||
/api/materials/{id}:
|
||||
delete:
|
||||
summary: Delete a material by ID
|
||||
tags:
|
||||
- Materials
|
||||
security:
|
||||
- BearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'204':
|
||||
description: Material deleted successfully
|
||||
'400':
|
||||
description: Bad Request - Id not a positive integer
|
||||
'401':
|
||||
description: Unauthorized - Missing or invalid token
|
||||
'404':
|
||||
description: Not Found - No material with that id belongs to this user
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
BearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
|
||||
parameters:
|
||||
IdParam:
|
||||
name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: integer }
|
||||
SearchQuery:
|
||||
name: search
|
||||
in: query
|
||||
schema: { type: string }
|
||||
SortBy:
|
||||
name: sortBy
|
||||
in: query
|
||||
schema: { type: string, enum: [name, date_created, id] }
|
||||
Limit:
|
||||
name: limit
|
||||
in: query
|
||||
schema: { type: integer, default: 10 }
|
||||
Offset:
|
||||
name: offset
|
||||
in: query
|
||||
schema: { type: integer, default: 0 }
|
||||
|
||||
schemas:
|
||||
SignupRequest:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
example: new_user_1
|
||||
password:
|
||||
type: string
|
||||
format: password
|
||||
example: newpassword1234
|
||||
|
||||
LoginRequest:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
example: new_user_1
|
||||
password:
|
||||
type: string
|
||||
format: password
|
||||
example: newpassword1234
|
||||
|
||||
UserResponse:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
example: 10
|
||||
username:
|
||||
type: string
|
||||
example: new_user_1
|
||||
|
||||
LoginResponse:
|
||||
type: object
|
||||
properties:
|
||||
accessToken:
|
||||
type: string
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
Idea:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
readOnly: true
|
||||
example: 1
|
||||
name:
|
||||
type: string
|
||||
example: AI-Powered Task Manager
|
||||
description:
|
||||
type: string
|
||||
example: A web app that uses AI to prioritize tasks intelligently
|
||||
date_created:
|
||||
type: string
|
||||
format: date-time
|
||||
readOnly: true
|
||||
|
||||
IdeaRequest:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
- description
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: AI-Powered Task Manager
|
||||
description:
|
||||
type: string
|
||||
example: A web app that uses AI to prioritize tasks intelligently
|
||||
|
||||
IdeaUpdateRequest:
|
||||
type: object
|
||||
description: At least one field must be provided
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: AI-Powered Task Manager
|
||||
description:
|
||||
type: string
|
||||
example: A web app that uses AI to prioritize tasks intelligently
|
||||
|
||||
Project:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
readOnly: true
|
||||
example: 1
|
||||
name:
|
||||
type: string
|
||||
example: Project 1
|
||||
description:
|
||||
type: string
|
||||
example: Project 1 description
|
||||
date_created:
|
||||
type: string
|
||||
format: date-time
|
||||
readOnly: true
|
||||
files:
|
||||
type: array
|
||||
readOnly: true
|
||||
items:
|
||||
$ref: '#/components/schemas/File'
|
||||
|
||||
ProjectRequest:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
- description
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: Project 1
|
||||
description:
|
||||
type: string
|
||||
example: Project 1 description
|
||||
|
||||
ProjectUpdateRequest:
|
||||
type: object
|
||||
description: At least one field must be provided
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: Project 1
|
||||
description:
|
||||
type: string
|
||||
example: Project 1 description
|
||||
|
||||
Material:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
readOnly: true
|
||||
example: 1
|
||||
projectId:
|
||||
type: integer
|
||||
example: 1
|
||||
name:
|
||||
type: string
|
||||
example: Resource 1
|
||||
description:
|
||||
type: string
|
||||
example: Resource 1 description
|
||||
source:
|
||||
type: string
|
||||
example: Source 1
|
||||
author:
|
||||
type: string
|
||||
example: Author 1
|
||||
text:
|
||||
type: string
|
||||
example: Resource 1 text
|
||||
|
||||
MaterialRequest:
|
||||
type: object
|
||||
required:
|
||||
- projectId
|
||||
- name
|
||||
- description
|
||||
- source
|
||||
- author
|
||||
- text
|
||||
properties:
|
||||
projectId:
|
||||
type: integer
|
||||
example: 1
|
||||
name:
|
||||
type: string
|
||||
example: Resource 1
|
||||
description:
|
||||
type: string
|
||||
example: Resource 1 description
|
||||
source:
|
||||
type: string
|
||||
example: Source 1
|
||||
author:
|
||||
type: string
|
||||
example: Author 1
|
||||
text:
|
||||
type: string
|
||||
example: Resource 1 text
|
||||
|
||||
File:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: integer }
|
||||
projectId: { type: integer }
|
||||
name: { type: string }
|
||||
size: { type: integer }
|
||||
mimeType: { type: string }
|
||||
Reference in New Issue
Block a user