-
Notifications
You must be signed in to change notification settings - Fork 7
Add maintenance notifications in PAC portal during any related mainte… #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| package mongodb | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "time" | ||
|
|
||
| "github.com/IBM/power-access-cloud/api/internal/pkg/pac-go-server/models" | ||
| "go.mongodb.org/mongo-driver/bson" | ||
| "go.mongodb.org/mongo-driver/bson/primitive" | ||
| "go.mongodb.org/mongo-driver/mongo" | ||
| ) | ||
|
|
||
| // GetAllMaintenanceWindows retrieves all non-deleted maintenance windows from the database | ||
| func (db *MongoDB) GetAllMaintenanceWindows() ([]models.MaintenanceWindow, error) { | ||
| collection := db.Database.Collection("maintenance_windows") | ||
| ctx, cancel := context.WithTimeout(context.Background(), dbContextTimeout) | ||
| defer cancel() | ||
|
|
||
| // Filter out soft-deleted records | ||
| filter := bson.M{"deleted_at": bson.M{"$exists": false}} | ||
| cursor, err := collection.Find(ctx, filter) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("error fetching maintenance windows from DB: %w", err) | ||
| } | ||
| defer cursor.Close(ctx) | ||
|
|
||
| var windows []models.MaintenanceWindow | ||
| if err := cursor.All(ctx, &windows); err != nil { | ||
| return nil, fmt.Errorf("error decoding maintenance windows: %w", err) | ||
| } | ||
|
|
||
| return windows, nil | ||
| } | ||
|
|
||
| // GetMaintenanceWindowByID retrieves a specific non-deleted maintenance window by ID | ||
| func (db *MongoDB) GetMaintenanceWindowByID(id string) (*models.MaintenanceWindow, error) { | ||
| collection := db.Database.Collection("maintenance_windows") | ||
| ctx, cancel := context.WithTimeout(context.Background(), dbContextTimeout) | ||
| defer cancel() | ||
|
|
||
| objectID, err := primitive.ObjectIDFromHex(id) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("invalid maintenance window ID: %w", err) | ||
| } | ||
|
|
||
| var window models.MaintenanceWindow | ||
| // Filter out soft-deleted records | ||
| filter := bson.M{ | ||
| "_id": objectID, | ||
| "deleted_at": bson.M{"$exists": false}, | ||
| } | ||
|
|
||
| err = collection.FindOne(ctx, filter).Decode(&window) | ||
| if err != nil { | ||
| if err == mongo.ErrNoDocuments { | ||
| return nil, nil | ||
| } | ||
| return nil, fmt.Errorf("error fetching maintenance window from DB: %w", err) | ||
| } | ||
|
|
||
| return &window, nil | ||
| } | ||
|
|
||
| // CreateMaintenanceWindow creates a new maintenance window | ||
| func (db *MongoDB) CreateMaintenanceWindow(window *models.MaintenanceWindow) error { | ||
| collection := db.Database.Collection("maintenance_windows") | ||
| ctx, cancel := context.WithTimeout(context.Background(), dbContextTimeout) | ||
| defer cancel() | ||
|
|
||
| _, err := collection.InsertOne(ctx, window) | ||
| if err != nil { | ||
| return fmt.Errorf("error creating maintenance window: %w", err) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| // UpdateMaintenanceWindow updates an existing maintenance window | ||
| func (db *MongoDB) UpdateMaintenanceWindow(window *models.MaintenanceWindow) error { | ||
| collection := db.Database.Collection("maintenance_windows") | ||
| ctx, cancel := context.WithTimeout(context.Background(), dbContextTimeout) | ||
| defer cancel() | ||
|
|
||
| filter := bson.M{"_id": window.ID} | ||
| update := bson.M{ | ||
| "$set": bson.M{ | ||
| "enabled": window.Enabled, | ||
| "start_time": window.StartTime, | ||
| "end_time": window.EndTime, | ||
| "message": window.Message, | ||
| "updated_by": window.UpdatedBy, | ||
| "updated_at": window.UpdatedAt, | ||
| }, | ||
| } | ||
|
|
||
| result, err := collection.UpdateOne(ctx, filter, update) | ||
| if err != nil { | ||
| return fmt.Errorf("error updating maintenance window: %w", err) | ||
| } | ||
|
|
||
| if result.MatchedCount == 0 { | ||
| return fmt.Errorf("maintenance window not found") | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| // DeleteMaintenanceWindow performs soft delete on a maintenance window by ID | ||
| func (db *MongoDB) DeleteMaintenanceWindow(id string, deletedBy string, deletedAt *time.Time) error { | ||
| collection := db.Database.Collection("maintenance_windows") | ||
| ctx, cancel := context.WithTimeout(context.Background(), dbContextTimeout) | ||
| defer cancel() | ||
|
|
||
| objectID, err := primitive.ObjectIDFromHex(id) | ||
| if err != nil { | ||
| return fmt.Errorf("invalid maintenance window ID: %w", err) | ||
| } | ||
|
|
||
| // Only soft delete non-deleted records | ||
| filter := bson.M{ | ||
| "_id": objectID, | ||
| "deleted_at": bson.M{"$exists": false}, | ||
| } | ||
|
|
||
| update := bson.M{ | ||
| "$set": bson.M{ | ||
| "deleted_by": deletedBy, | ||
| "deleted_at": deletedAt, | ||
| }, | ||
| } | ||
|
|
||
| result, err := collection.UpdateOne(ctx, filter, update) | ||
| if err != nil { | ||
| return fmt.Errorf("error soft deleting maintenance window: %w", err) | ||
| } | ||
|
|
||
| if result.MatchedCount == 0 { | ||
| return fmt.Errorf("maintenance window not found or already deleted") | ||
| } | ||
|
|
||
| return nil | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| package models | ||
|
|
||
| import ( | ||
| "time" | ||
|
|
||
| "go.mongodb.org/mongo-driver/bson/primitive" | ||
| ) | ||
|
|
||
| // MaintenanceWindow represents a single maintenance notification window | ||
| type MaintenanceWindow struct { | ||
| ID primitive.ObjectID `bson:"_id" json:"id"` | ||
| Enabled bool `bson:"enabled" json:"enabled"` | ||
| StartTime time.Time `bson:"start_time" json:"start_time"` | ||
| EndTime time.Time `bson:"end_time" json:"end_time"` | ||
| Message string `bson:"message" json:"message"` | ||
| CreatedBy string `bson:"created_by" json:"created_by"` | ||
| CreatedAt time.Time `bson:"created_at" json:"created_at"` | ||
| UpdatedBy string `bson:"updated_by" json:"updated_by"` | ||
| UpdatedAt time.Time `bson:"updated_at" json:"updated_at"` | ||
| DeletedBy string `bson:"deleted_by,omitempty" json:"deleted_by,omitempty"` | ||
| DeletedAt *time.Time `bson:"deleted_at,omitempty" json:"deleted_at,omitempty"` | ||
| } | ||
|
|
||
| // MaintenanceResponse is the public response for a single maintenance window | ||
| type MaintenanceResponse struct { | ||
| ID string `json:"id"` | ||
| Enabled bool `json:"enabled"` | ||
| StartTime time.Time `json:"start_time"` | ||
| EndTime time.Time `json:"end_time"` | ||
| Message string `json:"message"` | ||
| IsActive bool `json:"is_active"` | ||
| } | ||
|
|
||
| // MaintenanceAdminResponse is the admin response with audit fields | ||
| type MaintenanceAdminResponse struct { | ||
| ID string `json:"id"` | ||
| Enabled bool `json:"enabled"` | ||
| StartTime time.Time `json:"start_time"` | ||
| EndTime time.Time `json:"end_time"` | ||
| Message string `json:"message"` | ||
| IsActive bool `json:"is_active"` | ||
| CreatedBy string `json:"created_by"` | ||
| CreatedAt time.Time `json:"created_at"` | ||
| UpdatedBy string `json:"updated_by,omitempty"` | ||
| UpdatedAt time.Time `json:"updated_at,omitempty"` | ||
| DeletedBy string `json:"deleted_by,omitempty"` | ||
| DeletedAt *time.Time `json:"deleted_at,omitempty"` | ||
| } | ||
|
|
||
| // MaintenanceListResponse is the public response for listing all maintenance windows | ||
| type MaintenanceListResponse struct { | ||
| Maintenances []MaintenanceResponse `json:"maintenances"` | ||
| } | ||
|
|
||
| // MaintenanceAdminListResponse is the admin response for listing all maintenance windows with pagination | ||
| type MaintenanceAdminListResponse struct { | ||
| TotalPages int64 `json:"total_pages"` | ||
| TotalItems int64 `json:"total_items"` | ||
| Maintenances []MaintenanceAdminResponse `json:"maintenances"` | ||
| Links Links `json:"links"` | ||
| } | ||
|
|
||
| // MaintenanceCreateRequest is the request body for creating a new maintenance window | ||
| type MaintenanceCreateRequest struct { | ||
| Enabled bool `json:"enabled"` | ||
| StartTime time.Time `json:"start_time" binding:"required"` | ||
| EndTime time.Time `json:"end_time" binding:"required"` | ||
| Message string `json:"message" binding:"required"` | ||
| } | ||
|
|
||
| // MaintenanceUpdateRequest is the request body for updating an existing maintenance window | ||
| type MaintenanceUpdateRequest struct { | ||
| Enabled bool `json:"enabled"` | ||
| StartTime time.Time `json:"start_time,omitempty"` | ||
| EndTime time.Time `json:"end_time,omitempty"` | ||
| Message string `json:"message,omitempty"` | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -94,6 +94,10 @@ func CreateRouter() *gin.Engine { | |
| authorizedAdmin.GET("/users/:id", services.GetUser) | ||
|
|
||
| authorizedAdmin.GET("/feedbacks", services.GetFeedback) | ||
|
|
||
| authorizedAdmin.POST("/maintenance", services.CreateMaintenanceWindow) | ||
| authorizedAdmin.PUT("/maintenance/:id", services.UpdateMaintenanceWindow) | ||
| authorizedAdmin.DELETE("/maintenance/:id", services.DeleteMaintenanceWindow) | ||
| } | ||
|
|
||
| // user related endpoints | ||
|
|
@@ -124,5 +128,8 @@ func CreateRouter() *gin.Engine { | |
| // feedback related endpoints | ||
| authorized.POST("/feedbacks", services.CreateFeedback) | ||
|
|
||
| // maintenance notification related endpoints | ||
| authorized.GET("/maintenance", services.GetMaintenanceWindows) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldnt GetAllMaintenances be only admin route?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, We need this call to get the maintenance windows and show the active one to the users |
||
|
|
||
| return router | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List of all maintenances is not required for public, this would be required for admin only for auditing or some other purposes