refactor: improve handling of optional CustomerID in project models and DTOs
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
This commit is contained in:
parent
a9c7598862
commit
4b47da3673
@ -12,7 +12,7 @@ type ProjectDto struct {
|
|||||||
UpdatedAt time.Time `json:"updatedAt" example:"2024-01-01T00:00:00Z"`
|
UpdatedAt time.Time `json:"updatedAt" example:"2024-01-01T00:00:00Z"`
|
||||||
LastEditorID string `json:"lastEditorID" example:"01HGW2BBG0000000000000000"`
|
LastEditorID string `json:"lastEditorID" example:"01HGW2BBG0000000000000000"`
|
||||||
Name string `json:"name" example:"Time Tracking App"`
|
Name string `json:"name" example:"Time Tracking App"`
|
||||||
CustomerID *string `json:"customerId" example:"01HGW2BBG0000000000000000"`
|
CustomerID *string `json:"customerId,omitempty" example:"01HGW2BBG0000000000000000"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectCreateDto struct {
|
type ProjectCreateDto struct {
|
||||||
|
@ -148,13 +148,17 @@ func (h *ProjectHandler) DeleteProject(c *gin.Context) {
|
|||||||
// Helper functions for DTO conversion
|
// Helper functions for DTO conversion
|
||||||
|
|
||||||
func convertProjectToDTO(project *models.Project) dto.ProjectDto {
|
func convertProjectToDTO(project *models.Project) dto.ProjectDto {
|
||||||
customerId := project.CustomerID.String()
|
var customerIdPtr *string
|
||||||
|
if project.CustomerID != nil {
|
||||||
|
customerIdStr := project.CustomerID.String()
|
||||||
|
customerIdPtr = &customerIdStr
|
||||||
|
}
|
||||||
return dto.ProjectDto{
|
return dto.ProjectDto{
|
||||||
ID: project.ID.String(),
|
ID: project.ID.String(),
|
||||||
CreatedAt: project.CreatedAt,
|
CreatedAt: project.CreatedAt,
|
||||||
UpdatedAt: project.UpdatedAt,
|
UpdatedAt: project.UpdatedAt,
|
||||||
Name: project.Name,
|
Name: project.Name,
|
||||||
CustomerID: &customerId,
|
CustomerID: customerIdPtr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,13 +186,13 @@ func convertUpdateProjectDTOToModel(dto dto.ProjectUpdateDto, id types.ULID) (mo
|
|||||||
|
|
||||||
if dto.CustomerID.Valid {
|
if dto.CustomerID.Valid {
|
||||||
if dto.CustomerID.Value == nil {
|
if dto.CustomerID.Value == nil {
|
||||||
update.CustomerID = nil
|
update.CustomerID = types.Null[types.ULID]()
|
||||||
} else {
|
} else {
|
||||||
customerID, err := types.ULIDFromString(*dto.CustomerID.Value)
|
customerID, err := types.ULIDFromString(*dto.CustomerID.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.ProjectUpdate{}, fmt.Errorf("invalid customer ID: %w", err)
|
return models.ProjectUpdate{}, fmt.Errorf("invalid customer ID: %w", err)
|
||||||
}
|
}
|
||||||
update.CustomerID = &customerID
|
update.CustomerID = types.NewNullable(customerID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ func MigrateDB() error {
|
|||||||
// createConnection creates a new database connection with the given configuration
|
// createConnection creates a new database connection with the given configuration
|
||||||
func createConnection(dbConfig config.DatabaseConfig, dbName string) (*gorm.DB, error) {
|
func createConnection(dbConfig config.DatabaseConfig, dbName string) (*gorm.DB, error) {
|
||||||
// Create DSN (Data Source Name)
|
// Create DSN (Data Source Name)
|
||||||
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbName=%s sslmode=%s",
|
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
|
||||||
dbConfig.Host, dbConfig.Port, dbConfig.User, dbConfig.Password, dbName, dbConfig.SSLMode)
|
dbConfig.Host, dbConfig.Port, dbConfig.User, dbConfig.Password, dbName, dbConfig.SSLMode)
|
||||||
|
|
||||||
// Configure GORM logger
|
// Configure GORM logger
|
||||||
|
@ -90,7 +90,7 @@ func UpdateModel(ctx context.Context, model any, updates any) error {
|
|||||||
updateMap := make(map[string]any)
|
updateMap := make(map[string]any)
|
||||||
|
|
||||||
// Iterate through all fields
|
// Iterate through all fields
|
||||||
for i := 0; i < updateValue.NumField(); i++ {
|
for i := range updateValue.NumField() {
|
||||||
field := updateValue.Field(i)
|
field := updateValue.Field(i)
|
||||||
fieldType := updateType.Field(i)
|
fieldType := updateType.Field(i)
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
type Project struct {
|
type Project struct {
|
||||||
EntityBase
|
EntityBase
|
||||||
Name string `gorm:"column:name;not null"`
|
Name string `gorm:"column:name;not null"`
|
||||||
CustomerID *types.ULID `gorm:"column:customer_id;type:bytea;not null"`
|
CustomerID *types.ULID `gorm:"column:customer_id;type:bytea;index"`
|
||||||
|
|
||||||
// Relationships (for Eager Loading)
|
// Relationships (for Eager Loading)
|
||||||
Customer *Customer `gorm:"foreignKey:CustomerID"`
|
Customer *Customer `gorm:"foreignKey:CustomerID"`
|
||||||
@ -33,9 +33,9 @@ type ProjectCreate struct {
|
|||||||
|
|
||||||
// ProjectUpdate contains the updatable fields of a project
|
// ProjectUpdate contains the updatable fields of a project
|
||||||
type ProjectUpdate struct {
|
type ProjectUpdate struct {
|
||||||
ID types.ULID `gorm:"-"` // Exclude from updates
|
ID types.ULID `gorm:"-"` // Exclude from updates
|
||||||
Name *string `gorm:"column:name"`
|
Name *string `gorm:"column:name"`
|
||||||
CustomerID *types.ULID `gorm:"column:customer_id"`
|
CustomerID types.Nullable[types.ULID] `gorm:"column:customer_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the Create struct contains valid data
|
// Validate checks if the Create struct contains valid data
|
||||||
@ -44,7 +44,7 @@ func (pc *ProjectCreate) Validate() error {
|
|||||||
return errors.New("project name cannot be empty")
|
return errors.New("project name cannot be empty")
|
||||||
}
|
}
|
||||||
// Check for valid CustomerID
|
// Check for valid CustomerID
|
||||||
if pc.CustomerID.Compare(types.ULID{}) == 0 {
|
if pc.CustomerID != nil && pc.CustomerID.Compare(types.ULID{}) == 0 {
|
||||||
return errors.New("customerID cannot be empty")
|
return errors.New("customerID cannot be empty")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -122,7 +122,7 @@ func CreateProject(ctx context.Context, create ProjectCreate) (*Project, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the customer exists
|
// Check if the customer exists
|
||||||
if create.CustomerID == nil {
|
if create.CustomerID != nil {
|
||||||
customer, err := GetCustomerByID(ctx, *create.CustomerID)
|
customer, err := GetCustomerByID(ctx, *create.CustomerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error checking the customer: %w", err)
|
return nil, fmt.Errorf("error checking the customer: %w", err)
|
||||||
@ -160,13 +160,18 @@ func UpdateProject(ctx context.Context, update ProjectUpdate) (*Project, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If CustomerID is updated, check if the customer exists
|
// If CustomerID is updated, check if the customer exists
|
||||||
if update.CustomerID != nil {
|
if update.CustomerID.Valid {
|
||||||
customer, err := GetCustomerByID(ctx, *update.CustomerID)
|
if update.CustomerID.Value != nil {
|
||||||
if err != nil {
|
customer, err := GetCustomerByID(ctx, *update.CustomerID.Value)
|
||||||
return nil, fmt.Errorf("error checking the customer: %w", err)
|
if err != nil {
|
||||||
}
|
return nil, fmt.Errorf("error checking the customer: %w", err)
|
||||||
if customer == nil {
|
}
|
||||||
return nil, errors.New("the specified customer does not exist")
|
if customer == nil {
|
||||||
|
return nil, errors.New("the specified customer does not exist")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If CustomerID is nil, set it to nil in the project
|
||||||
|
project.CustomerID = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ func (uc *UserCreate) Validate() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if uc.CompanyID.Compare(types.ULID{}) == 0 {
|
if uc.CompanyID != nil && uc.CompanyID.Compare(types.ULID{}) == 0 {
|
||||||
return errors.New("companyID cannot be empty")
|
return errors.New("companyID cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,13 +363,15 @@ func CreateUser(ctx context.Context, create UserCreate) (*User, error) {
|
|||||||
return errors.New("email is already in use")
|
return errors.New("email is already in use")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if company exists
|
if create.CompanyID != nil {
|
||||||
var companyCount int64
|
// Check if company exists
|
||||||
if err := tx.Model(&Company{}).Where("id = ?", create.CompanyID).Count(&companyCount).Error; err != nil {
|
var companyCount int64
|
||||||
return fmt.Errorf("error checking company: %w", err)
|
if err := tx.Model(&Company{}).Where("id = ?", create.CompanyID).Count(&companyCount).Error; err != nil {
|
||||||
}
|
return fmt.Errorf("error checking company: %w", err)
|
||||||
if companyCount == 0 {
|
}
|
||||||
return errors.New("the specified company does not exist")
|
if companyCount == 0 {
|
||||||
|
return errors.New("the specified company does not exist")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash password with unique salt
|
// Hash password with unique salt
|
||||||
|
168
backend/postman/activity.postman_collection.json
Normal file
168
backend/postman/activity.postman_collection.json
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "YOUR_POSTMAN_ID",
|
||||||
|
"name": "Activity API",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "GET /api/activities",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/activities",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"activities"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/activities/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/activities/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"activities",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "POST /api/activities",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"name\": \"\",\n\t\"billingRate\": 0\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/activities",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"activities"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PUT /api/activities/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"name\": \"\",\n\t\"billingRate\": 0\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/activities/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"activities",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DELETE /api/activities/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "DELETE",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/activities/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"activities",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
168
backend/postman/company.postman_collection.json
Normal file
168
backend/postman/company.postman_collection.json
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "YOUR_POSTMAN_ID",
|
||||||
|
"name": "Company API",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "GET /api/companies",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/companies",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"companies"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/companies/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/companies/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"companies",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "POST /api/companies",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"name\": \"\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/companies",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"companies"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PUT /api/companies/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"name\": \"\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/companies/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"companies",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DELETE /api/companies/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "DELETE",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/companies/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"companies",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
200
backend/postman/customer.postman_collection.json
Normal file
200
backend/postman/customer.postman_collection.json
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "YOUR_POSTMAN_ID",
|
||||||
|
"name": "Customer API",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "GET /api/customers",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/customers",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"customers"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/customers/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/customers/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"customers",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/customers/company/:companyId",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/customers/company/:companyId",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"customers",
|
||||||
|
"company",
|
||||||
|
":companyId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "companyId",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "POST /api/customers",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"name\": \"\",\n\t\"companyId\": \"\",\n\t\"ownerUserID\": \"\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/customers",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"customers"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PUT /api/customers/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"name\": \"\",\n\t\"companyId\": \"\",\n\t\"ownerUserID\": \"\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/customers/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"customers",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DELETE /api/customers/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "DELETE",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/customers/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"customers",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
225
backend/postman/project.postman_collection.json
Normal file
225
backend/postman/project.postman_collection.json
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "YOUR_POSTMAN_ID",
|
||||||
|
"name": "Project API",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "GET /api/projects",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/projects",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"projects"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/projects/with-customers",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/projects/with-customers",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"projects",
|
||||||
|
"with-customers"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/projects/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/projects/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"projects",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/projects/customer/:customerId",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/projects/customer/:customerId",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"projects",
|
||||||
|
"customer",
|
||||||
|
":customerId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "customerId",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "POST /api/projects",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"name\": \"\",\n\t\"customerId\": \"\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/projects",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"projects"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PUT /api/projects/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"name\": \"\",\n\t\"customerId\": \"\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/projects/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"projects",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DELETE /api/projects/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "DELETE",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/projects/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"projects",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
292
backend/postman/timeentry.postman_collection.json
Normal file
292
backend/postman/timeentry.postman_collection.json
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "YOUR_POSTMAN_ID",
|
||||||
|
"name": "TimeEntry API",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "GET /api/time-entries",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/time-entries",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"time-entries"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/time-entries/me",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/time-entries/me",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"time-entries",
|
||||||
|
"me"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/time-entries/range",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/time-entries/range?start=2023-01-01T00:00:00Z&end=2023-01-02T00:00:00Z",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"time-entries",
|
||||||
|
"range"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "start",
|
||||||
|
"value": "2023-01-01T00:00:00Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "end",
|
||||||
|
"value": "2023-01-02T00:00:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/time-entries/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/time-entries/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"time-entries",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/time-entries/user/:userId",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/time-entries/user/:userId",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"time-entries",
|
||||||
|
"user",
|
||||||
|
":userId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "userId",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/time-entries/project/:projectId",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/time-entries/project/:projectId",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"time-entries",
|
||||||
|
"project",
|
||||||
|
":projectId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "projectId",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "POST /api/time-entries",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"userID\": \"\",\n \"projectID\": \"\",\n \"activityID\": \"\",\n \"start\": \"2023-01-01T00:00:00Z\",\n \"end\": \"2023-01-01T01:00:00Z\",\n \"description\": \"\",\n \"billable\": true\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/time-entries",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"time-entries"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PUT /api/time-entries/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"userID\": \"\",\n \"projectID\": \"\",\n \"activityID\": \"\",\n \"start\": \"2023-01-01T00:00:00Z\",\n \"end\": \"2023-01-01T01:00:00Z\",\n \"description\": \"\",\n \"billable\": true\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/time-entries/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"time-entries",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DELETE /api/time-entries/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "DELETE",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/time-entries/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"time-entries",
|
||||||
|
":id"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "id",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
241
backend/postman/user.postman_collection.json
Normal file
241
backend/postman/user.postman_collection.json
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "YOUR_POSTMAN_ID",
|
||||||
|
"name": "User API",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Auth",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "POST /api/auth/login",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"email\": \"\",\n\t\"password\": \"\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/auth/login",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"auth",
|
||||||
|
"login"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "POST /api/auth/register",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"email\": \"\",\n\t\"password\": \"\",\n\t\"role\": \"user\",\n\t\"companyID\": \"\",\n\t\"hourlyRate\": 0\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/auth/register",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"auth",
|
||||||
|
"register"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/auth/me",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/auth/me",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"auth",
|
||||||
|
"me"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Users",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "GET /api/users",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/users",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"users"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GET /api/users/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/users/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"users",
|
||||||
|
":id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "POST /api/users",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"email\": \"\",\n\t\"password\": \"\",\n\t\"role\": \"user\",\n\t\"companyID\": \"\",\n\t\"hourlyRate\": 0\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/users",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"users"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PUT /api/users/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n\t\"email\": \"\",\n\t\"password\": \"\",\n\t\"role\": \"user\",\n\t\"companyID\": \"\",\n\t\"hourlyRate\": 0\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/users/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"users",
|
||||||
|
":id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DELETE /api/users/:id",
|
||||||
|
"request": {
|
||||||
|
"method": "DELETE",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer {{JWT_TOKEN}}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{API_URL}}/api/users/:id",
|
||||||
|
"host": [
|
||||||
|
"{{API_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"users",
|
||||||
|
":id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
113
flake.nix
Normal file
113
flake.nix
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
{
|
||||||
|
description = "Development environment for Go and Next.js (TypeScript)";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
config = {
|
||||||
|
allowUnfree = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Go development tools
|
||||||
|
goPackages = with pkgs; [
|
||||||
|
go
|
||||||
|
gopls
|
||||||
|
golangci-lint
|
||||||
|
delve
|
||||||
|
go-outline
|
||||||
|
gotools
|
||||||
|
go-mockgen
|
||||||
|
gomodifytags
|
||||||
|
impl
|
||||||
|
gotests
|
||||||
|
];
|
||||||
|
|
||||||
|
# TypeScript/Next.js development tools
|
||||||
|
nodePackages = with pkgs; [
|
||||||
|
nodejs_20
|
||||||
|
nodePackages.typescript
|
||||||
|
nodePackages.typescript-language-server
|
||||||
|
nodePackages.yarn
|
||||||
|
nodePackages.pnpm
|
||||||
|
nodePackages.npm
|
||||||
|
nodePackages.prettier
|
||||||
|
nodePackages.eslint
|
||||||
|
nodePackages.next
|
||||||
|
];
|
||||||
|
|
||||||
|
# General development tools
|
||||||
|
commonPackages = with pkgs; [
|
||||||
|
git
|
||||||
|
gh
|
||||||
|
nixpkgs-fmt
|
||||||
|
pre-commit
|
||||||
|
ripgrep
|
||||||
|
jq
|
||||||
|
curl
|
||||||
|
coreutils
|
||||||
|
gnumake
|
||||||
|
];
|
||||||
|
|
||||||
|
# VSCode with extensions
|
||||||
|
vscodeWithExtensions = pkgs.vscode-with-extensions.override {
|
||||||
|
vscodeExtensions = with pkgs.vscode-extensions; [
|
||||||
|
golang.go # Go support
|
||||||
|
esbenp.prettier-vscode # Prettier
|
||||||
|
dbaeumer.vscode-eslint # ESLint
|
||||||
|
ms-vscode.vscode-typescript-tslint-plugin # TypeScript
|
||||||
|
bradlc.vscode-tailwindcss # Tailwind CSS support
|
||||||
|
jnoortheen.nix-ide # Nix support
|
||||||
|
] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [
|
||||||
|
{
|
||||||
|
name = "nextjs";
|
||||||
|
publisher = "pulkitgangwar";
|
||||||
|
version = "1.0.6";
|
||||||
|
sha256 = "sha256-L6ZgqNkM0qzSiTKiGfgQB9m3U0HmwLA3NZ9nrslQjeg=";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
buildInputs = goPackages ++ nodePackages ++ commonPackages ++ [ vscodeWithExtensions ];
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
echo "🚀 Welcome to the Go and Next.js (TypeScript) development environment!"
|
||||||
|
echo "📦 Available tools:"
|
||||||
|
echo " Go: $(go version)"
|
||||||
|
echo " Node: $(node --version)"
|
||||||
|
echo " TypeScript: $(tsc --version)"
|
||||||
|
echo " Next.js: $(npx next --version)"
|
||||||
|
echo ""
|
||||||
|
echo "🔧 Use 'code .' to open VSCode with the appropriate extensions"
|
||||||
|
echo "🔄 Run 'nix flake update' to update dependencies"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
GOROOT = "${pkgs.go}/share/go";
|
||||||
|
GOPATH = "$(pwd)/.go";
|
||||||
|
GO111MODULE = "on";
|
||||||
|
|
||||||
|
# NodeJS setup
|
||||||
|
NODE_OPTIONS = "--max-old-space-size=4096";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Optional: Add custom packages if needed
|
||||||
|
packages = {
|
||||||
|
# Example of a custom package or script if needed
|
||||||
|
# my-tool = ...
|
||||||
|
};
|
||||||
|
|
||||||
|
# Default package if someone runs `nix build`
|
||||||
|
defaultPackage = self.devShells.${system}.default;
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user