Skip to content

Commit

Permalink
Merge branch 'master' into Implement_Workflow_Request_Handler
Browse files Browse the repository at this point in the history
  • Loading branch information
MahtabBukhari authored Nov 22, 2024
2 parents 3ca1816 + d95a2f1 commit cc78ffb
Show file tree
Hide file tree
Showing 12 changed files with 750 additions and 72 deletions.
3 changes: 2 additions & 1 deletion db/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,15 @@ type Database interface {
GetWorkflowRequestByID(requestID string) (*WfRequest, error)
GetWorkflowRequestsByStatus(status WfRequestStatus) ([]WfRequest, error)
GetWorkflowRequest(requestID string) (*WfRequest, error)
UpdateWorkflowRequestStatusAndResponse(requestID string, status WfRequestStatus, responseData JSONB) error
UpdateWorkflowRequestStatusAndResponse(requestID string, status WfRequestStatus, responseData PropertyMap) error
GetWorkflowRequestsByWorkflowID(workflowID string) ([]WfRequest, error)
GetPendingWorkflowRequests(limit int) ([]WfRequest, error)
DeleteWorkflowRequest(requestID string) error
CreateProcessingMap(pm *WfProcessingMap) error
UpdateProcessingMap(pm *WfProcessingMap) error
GetProcessingMapByKey(processType, processKey string) (*WfProcessingMap, error)
GetProcessingMapsByType(processType string) ([]WfProcessingMap, error)
DeleteProcessingMapByKey(processType, processKey string) error
DeleteProcessingMap(id uint) error
ProcessReversePayments(paymentId uint) error
}
13 changes: 12 additions & 1 deletion db/workflow_db.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (db database) GetWorkflowRequest(requestID string) (*WfRequest, error) {
return &req, result.Error
}

func (db database) UpdateWorkflowRequestStatusAndResponse(requestID string, status WfRequestStatus, responseData JSONB) error {
func (db database) UpdateWorkflowRequestStatusAndResponse(requestID string, status WfRequestStatus, responseData PropertyMap) error {
if requestID == "" {
return errors.New("request ID cannot be empty")
}
Expand Down Expand Up @@ -192,6 +192,17 @@ func (db database) GetProcessingMapByKey(processType, processKey string) (*WfPro
return &pm, result.Error
}

func (db database) DeleteProcessingMapByKey(processType, processKey string) error {
if processType == "" || processKey == "" {
return errors.New("process type and key cannot be empty")
}

result := db.db.Where("type = ? AND process_key = ?", processType, processKey).
Delete(&WfProcessingMap{})

return result.Error
}

func (db database) GetProcessingMapsByType(processType string) ([]WfProcessingMap, error) {
if processType == "" {
return nil, errors.New("process type cannot be empty")
Expand Down
160 changes: 160 additions & 0 deletions handlers/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ type PostData struct {
FeatureUUID string `json:"featureUUID"`
}

type FeatureBriefRequest struct {
Output struct {
FeatureBrief string `json:"featureBrief"`
AudioLink string `json:"audioLink"`
FeatureUUID string `json:"featureUUID"`
} `json:"output"`
}
type AudioBriefPostData struct {
AudioLink string `json:"audioLink"`
FeatureUUID string `json:"featureUUID"`
Source string `json:"source"`
Examples []string `json:"examples"`
}

type featureHandler struct {
db db.Database
generateBountyHandler func(bounties []db.NewBounty) []db.BountyResponse
Expand Down Expand Up @@ -164,6 +178,64 @@ func (oh *featureHandler) GetFeatureByUuid(w http.ResponseWriter, r *http.Reques
json.NewEncoder(w).Encode(workspaceFeature)
}

func (oh *featureHandler) UpdateFeatureBrief(w http.ResponseWriter, r *http.Request) {

var req FeatureBriefRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Invalid request payload")
return
}

featureUUID := req.Output.FeatureUUID
newFeatureBrief := req.Output.FeatureBrief

if featureUUID == "" || newFeatureBrief == "" {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Missing required fields")
return
}

prevFeatureBrief := oh.db.GetFeatureByUuid(featureUUID)

if prevFeatureBrief.Uuid == "" {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Feature not found")
return
}

var updatedFeatureBrief string
if prevFeatureBrief.Brief == "" {
updatedFeatureBrief = newFeatureBrief
} else {

updatedFeatureBrief = prevFeatureBrief.Brief + "\n\n* Generated Feature Brief *\n\n" + newFeatureBrief
}

featureToUpdate := db.WorkspaceFeatures{
Uuid: featureUUID,
WorkspaceUuid: prevFeatureBrief.WorkspaceUuid,
Name: prevFeatureBrief.Name,
Brief: updatedFeatureBrief,
Requirements: prevFeatureBrief.Requirements,
Architecture: prevFeatureBrief.Architecture,
Url: prevFeatureBrief.Url,
Priority: prevFeatureBrief.Priority,
BountiesCountCompleted: prevFeatureBrief.BountiesCountCompleted,
BountiesCountAssigned: prevFeatureBrief.BountiesCountAssigned,
BountiesCountOpen: prevFeatureBrief.BountiesCountOpen,
}

p, err := oh.db.CreateOrEditFeature(featureToUpdate)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}

w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(p)
}

func (oh *featureHandler) CreateOrEditFeaturePhase(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string)
Expand Down Expand Up @@ -537,3 +609,91 @@ func (oh *featureHandler) StoriesSend(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(resp.StatusCode)
w.Write(respBody)
}

func (oh *featureHandler) BriefSend(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string)
if pubKeyFromAuth == "" {
fmt.Println("no pubkey from auth")
w.WriteHeader(http.StatusUnauthorized)
return
}

body, err := io.ReadAll(r.Body)
r.Body.Close()
if err != nil {
http.Error(w, "Failed to read requests body", http.StatusBadRequest)
return
}

var postData AudioBriefPostData
err = json.Unmarshal(body, &postData)
if err != nil {
fmt.Println("[BriefSend] JSON Unmarshal error:", err)
http.Error(w, "Invalid JSON format", http.StatusNotAcceptable)
return
}

host := os.Getenv("HOST")
if host == "" {
http.Error(w, "HOST environment variable not set", http.StatusInternalServerError)
return
}

completePostData := struct {
AudioBriefPostData
WebhookURL string `json:"webhook_url"`
}{
AudioBriefPostData: postData,
WebhookURL: fmt.Sprintf("%s/feature/brief", host),
}

apiKey := os.Getenv("SWWFKEY")
if apiKey == "" {
http.Error(w, "API key not set in environment", http.StatusInternalServerError)
return
}

stakworkPayload := map[string]interface{}{
"name": "string",
"workflow_id": 36928,
"workflow_params": map[string]interface{}{
"set_var": map[string]interface{}{
"attributes": map[string]interface{}{
"vars": completePostData,
},
},
},
}

stakworkPayloadJSON, err := json.Marshal(stakworkPayload)
if err != nil {
http.Error(w, "Failed to encode payload", http.StatusInternalServerError)
return
}

req, err := http.NewRequest(http.MethodPost, "https://api.stakwork.com/api/v1/projects", bytes.NewBuffer(stakworkPayloadJSON))
if err != nil {
http.Error(w, "Failed to create request to Stakwork API", http.StatusInternalServerError)
return
}
req.Header.Set("Authorization", "Token token="+apiKey)
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
http.Error(w, "Failed to send request to Stakwork API", http.StatusInternalServerError)
return
}
defer resp.Body.Close()

respBody, err := io.ReadAll(resp.Body)
if err != nil {
http.Error(w, "Failed to read response from Stakwork API", http.StatusInternalServerError)
return
}

w.WriteHeader(resp.StatusCode)
w.Write(respBody)
}
87 changes: 80 additions & 7 deletions handlers/people.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func NewPeopleHandler(db db.Database) *peopleHandler {
return &peopleHandler{db: db}
}

func (ph *peopleHandler) CreateOrEditPerson(w http.ResponseWriter, r *http.Request) {
func (ph *peopleHandler) CreatePerson(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string)
keys := r.URL.Query()
Expand All @@ -47,28 +47,29 @@ func (ph *peopleHandler) CreateOrEditPerson(w http.ResponseWriter, r *http.Reque
r.Body.Close()
err = json.Unmarshal(body, &person)
if err != nil {
fmt.Println(err)
log.Println(err)
w.WriteHeader(http.StatusNotAcceptable)
return
}

now := time.Now()

if pubKeyFromAuth == "" {
fmt.Println("no pubkey from auth")
log.Println("no pubkey from auth")
w.WriteHeader(http.StatusUnauthorized)
return
}
if pubKeyFromAuth != person.OwnerPubKey {
fmt.Println(pubKeyFromAuth)
fmt.Println(person.OwnerPubKey)
fmt.Println("mismatched pubkey")
log.Println(pubKeyFromAuth)
log.Println(person.OwnerPubKey)
log.Println("mismatched pubkey")
w.WriteHeader(http.StatusUnauthorized)
return
}

existing := ph.db.GetPersonByPubkey(pubKeyFromAuth)
if existing.ID == 0 {

person.UniqueName, _ = ph.db.PersonUniqueNameFromName(person.OwnerAlias)
person.Created = &now
person.Uuid = xid.New().String()
Expand All @@ -81,6 +82,79 @@ func (ph *peopleHandler) CreateOrEditPerson(w http.ResponseWriter, r *http.Reque
person.ReferredBy = referral.ID
}
}
} else {
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(existing)
return
}

person.OwnerPubKey = pubKeyFromAuth

if person.NewTicketTime != 0 {
go ph.db.ProcessAlerts(person)
}

b := new(bytes.Buffer)
decodeErr := json.NewEncoder(b).Encode(person.Extras)

if decodeErr != nil {
log.Printf("Could not encode extras json data")
}

p, err := ph.db.CreateOrEditPerson(person)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}

w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(p)
}

func (ph *peopleHandler) UpdatePerson(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string)

person := db.Person{}
body, err := io.ReadAll(r.Body)

if err != nil {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode("Sent wrong body data")
return
}

r.Body.Close()
err = json.Unmarshal(body, &person)
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusNotAcceptable)
return
}

now := time.Now()

if pubKeyFromAuth == "" {
log.Println("no pubkey from auth")
w.WriteHeader(http.StatusUnauthorized)
return
}

if pubKeyFromAuth != person.OwnerPubKey {
log.Println(pubKeyFromAuth)
log.Println(person.OwnerPubKey)
log.Println("mismatched pubkey")
w.WriteHeader(http.StatusUnauthorized)
return
}

existing := ph.db.GetPersonByPubkey(pubKeyFromAuth)
if existing.ID == 0 {
msg := fmt.Sprintf("User does not exists: %s", pubKeyFromAuth)
log.Println(msg)
w.WriteHeader(http.StatusNotFound)
json.NewEncoder(w).Encode(msg)
return
} else {
if person.OwnerPubKey != existing.OwnerPubKey && person.OwnerAlias != existing.OwnerAlias {
// can't edit someone else's
Expand All @@ -90,7 +164,6 @@ func (ph *peopleHandler) CreateOrEditPerson(w http.ResponseWriter, r *http.Reque
}
}

person.OwnerPubKey = pubKeyFromAuth
person.Updated = &now

if person.NewTicketTime != 0 {
Expand Down
Loading

0 comments on commit cc78ffb

Please sign in to comment.