-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2479 from aliraza556/feature/implement-snippet-ma…
…nagement feat: implement snippet management endpoints and db functions
- Loading branch information
Showing
8 changed files
with
1,159 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package db | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"time" | ||
|
||
"gorm.io/gorm" | ||
) | ||
|
||
func (db database) CreateSnippet(snippet *TextSnippet) (*TextSnippet, error) { | ||
if snippet.WorkspaceUUID == "" { | ||
return nil, errors.New("workspace UUID is required") | ||
} | ||
|
||
if snippet.Title == "" { | ||
return nil, errors.New("title is required") | ||
} | ||
|
||
if snippet.Snippet == "" { | ||
return nil, errors.New("snippet content is required") | ||
} | ||
|
||
now := time.Now() | ||
snippet.DateCreated = now | ||
snippet.LastEdited = now | ||
|
||
if err := db.db.Create(snippet).Error; err != nil { | ||
return nil, fmt.Errorf("failed to create snippet: %w", err) | ||
} | ||
|
||
return snippet, nil | ||
} | ||
|
||
func (db database) GetSnippetsByWorkspace(workspaceUUID string) ([]TextSnippet, error) { | ||
var snippets []TextSnippet | ||
|
||
if err := db.db.Where("workspace_uuid = ?", workspaceUUID).Find(&snippets).Error; err != nil { | ||
return nil, fmt.Errorf("failed to fetch snippets: %w", err) | ||
} | ||
|
||
return snippets, nil | ||
} | ||
|
||
func (db database) GetSnippetByID(id uint) (*TextSnippet, error) { | ||
var snippet TextSnippet | ||
|
||
if err := db.db.First(&snippet, id).Error; err != nil { | ||
if errors.Is(err, gorm.ErrRecordNotFound) { | ||
return nil, errors.New("record not found") | ||
} | ||
return nil, fmt.Errorf("failed to fetch snippet: %w", err) | ||
} | ||
|
||
return &snippet, nil | ||
} | ||
|
||
func (db database) UpdateSnippet(snippet *TextSnippet) (*TextSnippet, error) { | ||
if snippet.ID == 0 { | ||
return nil, errors.New("snippet ID is required") | ||
} | ||
|
||
snippet.LastEdited = time.Now() | ||
|
||
if err := db.db.Model(&TextSnippet{}).Where("id = ?", snippet.ID).Updates(snippet).Error; err != nil { | ||
return nil, fmt.Errorf("failed to update snippet: %w", err) | ||
} | ||
|
||
return db.GetSnippetByID(snippet.ID) | ||
} | ||
|
||
func (db database) DeleteSnippet(id uint) error { | ||
result := db.db.Delete(&TextSnippet{}, id) | ||
if result.Error != nil { | ||
return fmt.Errorf("failed to delete snippet: %w", result.Error) | ||
} | ||
|
||
if result.RowsAffected == 0 { | ||
return errors.New("snippet not found") | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
package handlers | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/go-chi/chi" | ||
"github.com/stakwork/sphinx-tribes/auth" | ||
"github.com/stakwork/sphinx-tribes/db" | ||
"github.com/stakwork/sphinx-tribes/logger" | ||
"github.com/stakwork/sphinx-tribes/utils" | ||
) | ||
|
||
type snippetHandler struct { | ||
httpClient HttpClient | ||
db db.Database | ||
} | ||
|
||
func NewSnippetHandler(httpClient HttpClient, db db.Database) *snippetHandler { | ||
return &snippetHandler{ | ||
httpClient: httpClient, | ||
db: db, | ||
} | ||
} | ||
|
||
type SnippetRequest struct { | ||
Title string `json:"title"` | ||
Snippet string `json:"snippet"` | ||
} | ||
|
||
func (sh *snippetHandler) CreateSnippet(w http.ResponseWriter, r *http.Request) { | ||
ctx := r.Context() | ||
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) | ||
|
||
if pubKeyFromAuth == "" { | ||
logger.Log.Info("[snippet] no pubkey from auth") | ||
w.WriteHeader(http.StatusUnauthorized) | ||
json.NewEncoder(w).Encode(map[string]string{"error": "Unauthorized"}) | ||
return | ||
} | ||
|
||
workspaceUUID := r.URL.Query().Get("workspace_uuid") | ||
if workspaceUUID == "" { | ||
http.Error(w, "workspace_uuid is required", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
var req SnippetRequest | ||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { | ||
http.Error(w, "Invalid request body", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
if req.Title == "" || req.Snippet == "" { | ||
http.Error(w, "Title and snippet are required", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
snippet := &db.TextSnippet{ | ||
WorkspaceUUID: workspaceUUID, | ||
Title: req.Title, | ||
Snippet: req.Snippet, | ||
} | ||
|
||
createdSnippet, err := sh.db.CreateSnippet(snippet) | ||
if err != nil { | ||
logger.Log.Error(fmt.Sprintf("Failed to create snippet: %v", err)) | ||
http.Error(w, "Failed to create snippet", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
w.WriteHeader(http.StatusCreated) | ||
json.NewEncoder(w).Encode(createdSnippet) | ||
} | ||
|
||
func (sh *snippetHandler) GetSnippetsByWorkspace(w http.ResponseWriter, r *http.Request) { | ||
ctx := r.Context() | ||
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) | ||
|
||
if pubKeyFromAuth == "" { | ||
logger.Log.Info("[snippet] no pubkey from auth") | ||
w.WriteHeader(http.StatusUnauthorized) | ||
json.NewEncoder(w).Encode(map[string]string{"error": "Unauthorized"}) | ||
return | ||
} | ||
|
||
workspaceUUID := chi.URLParam(r, "workspace_uuid") | ||
if workspaceUUID == "" { | ||
http.Error(w, "workspace_uuid is required", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
snippets, err := sh.db.GetSnippetsByWorkspace(workspaceUUID) | ||
if err != nil { | ||
logger.Log.Error(fmt.Sprintf("Failed to fetch snippets: %v", err)) | ||
http.Error(w, "Failed to fetch snippets", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
json.NewEncoder(w).Encode(snippets) | ||
} | ||
|
||
func (sh *snippetHandler) GetSnippetByID(w http.ResponseWriter, r *http.Request) { | ||
ctx := r.Context() | ||
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) | ||
|
||
if pubKeyFromAuth == "" { | ||
logger.Log.Info("[snippet] no pubkey from auth") | ||
w.WriteHeader(http.StatusUnauthorized) | ||
json.NewEncoder(w).Encode(map[string]string{"error": "Unauthorized"}) | ||
return | ||
} | ||
|
||
idStr := chi.URLParam(r, "id") | ||
id, err := utils.ConvertStringToUint(idStr) | ||
if err != nil { | ||
http.Error(w, "Invalid snippet ID", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
snippet, err := sh.db.GetSnippetByID(id) | ||
if err != nil { | ||
if err.Error() == "record not found" { | ||
http.Error(w, "Snippet not found", http.StatusNotFound) | ||
return | ||
} | ||
logger.Log.Error(fmt.Sprintf("Failed to fetch snippet: %v", err)) | ||
http.Error(w, "Failed to fetch snippet", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
json.NewEncoder(w).Encode(snippet) | ||
} | ||
|
||
func (sh *snippetHandler) UpdateSnippet(w http.ResponseWriter, r *http.Request) { | ||
ctx := r.Context() | ||
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) | ||
|
||
if pubKeyFromAuth == "" { | ||
logger.Log.Info("[snippet] no pubkey from auth") | ||
w.WriteHeader(http.StatusUnauthorized) | ||
json.NewEncoder(w).Encode(map[string]string{"error": "Unauthorized"}) | ||
return | ||
} | ||
|
||
idStr := chi.URLParam(r, "id") | ||
id, err := utils.ConvertStringToUint(idStr) | ||
if err != nil { | ||
http.Error(w, "Invalid snippet ID", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
var req SnippetRequest | ||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { | ||
http.Error(w, "Invalid request body", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
if req.Title == "" || req.Snippet == "" { | ||
http.Error(w, "Title and snippet are required", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
snippet := &db.TextSnippet{ | ||
ID: id, | ||
Title: req.Title, | ||
Snippet: req.Snippet, | ||
} | ||
|
||
updatedSnippet, err := sh.db.UpdateSnippet(snippet) | ||
if err != nil { | ||
if err.Error() == "record not found" { | ||
http.Error(w, "Snippet not found", http.StatusNotFound) | ||
return | ||
} | ||
logger.Log.Error(fmt.Sprintf("Failed to update snippet: %v", err)) | ||
http.Error(w, "Failed to update snippet", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
json.NewEncoder(w).Encode(updatedSnippet) | ||
} | ||
|
||
func (sh *snippetHandler) DeleteSnippet(w http.ResponseWriter, r *http.Request) { | ||
ctx := r.Context() | ||
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) | ||
|
||
if pubKeyFromAuth == "" { | ||
logger.Log.Info("[snippet] no pubkey from auth") | ||
w.WriteHeader(http.StatusUnauthorized) | ||
json.NewEncoder(w).Encode(map[string]string{"error": "Unauthorized"}) | ||
return | ||
} | ||
|
||
idStr := chi.URLParam(r, "id") | ||
id, err := utils.ConvertStringToUint(idStr) | ||
if err != nil { | ||
http.Error(w, "Invalid snippet ID", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
err = sh.db.DeleteSnippet(id) | ||
if err != nil { | ||
if err.Error() == "snippet not found" { | ||
http.Error(w, "Snippet not found", http.StatusNotFound) | ||
return | ||
} | ||
logger.Log.Error(fmt.Sprintf("Failed to delete snippet: %v", err)) | ||
http.Error(w, "Failed to delete snippet", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
w.WriteHeader(http.StatusOK) | ||
json.NewEncoder(w).Encode(map[string]string{"message": "Snippet deleted successfully"}) | ||
} |
Oops, something went wrong.