Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 8 additions & 34 deletions mattermost-plugin-issues/server/api_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,20 @@ type IssueContext struct {
CycleName string `json:"cycle_name,omitempty"`
}

// GET /api/v1/context/general
func (p *Plugin) handleGetGeneralContext(w http.ResponseWriter, _ *http.Request) {
func (p *Plugin) handleGetGeneralContext(w http.ResponseWriter, r *http.Request) {
companyInfo, err := p.store.GetCompanyInfo()
if err != nil {
respondError(w, http.StatusInternalServerError, err.Error())
return
}

projects, err := p.store.ListProjects()
projects, err := p.listProjectsForRequest(r)
if err != nil {
respondError(w, http.StatusInternalServerError, err.Error())
return
}

result := GeneralContext{
Company: companyInfo,
Projects: make([]ProjectContext, 0, len(projects)),
}

result := GeneralContext{Company: companyInfo, Projects: make([]ProjectContext, 0, len(projects))}
totalIssues := 0
openIssues := 0

Expand Down Expand Up @@ -77,15 +72,9 @@ func (p *Plugin) handleGetGeneralContext(w http.ResponseWriter, _ *http.Request)
}
}

result.Projects = append(result.Projects, ProjectContext{
Project: project,
Issues: issues,
Labels: labels,
Cycles: cycles,
})
result.Projects = append(result.Projects, ProjectContext{Project: project, Issues: issues, Labels: labels, Cycles: cycles})
}

// Fill in live stats if company info exists.
if result.Company != nil {
result.Company.State.ActiveProjects = len(projects)
result.Company.State.TotalIssues = totalIssues
Expand All @@ -95,11 +84,10 @@ func (p *Plugin) handleGetGeneralContext(w http.ResponseWriter, _ *http.Request)
respondJSON(w, http.StatusOK, result)
}

// GET /api/v1/projects/{id}/context
func (p *Plugin) handleGetProjectContext(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

project, err := p.store.GetProject(id)
project, err := p.getProjectForRequest(r, id)
if err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
Expand All @@ -121,52 +109,38 @@ func (p *Plugin) handleGetProjectContext(w http.ResponseWriter, r *http.Request)
return
}

respondJSON(w, http.StatusOK, ProjectContext{
Project: project,
Issues: issues,
Labels: labels,
Cycles: cycles,
})
respondJSON(w, http.StatusOK, ProjectContext{Project: project, Issues: issues, Labels: labels, Cycles: cycles})
}

// GET /api/v1/issues/{id}/context
func (p *Plugin) handleGetIssueContext(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

issue, err := p.store.GetIssue(id)
issue, err := p.getIssueForRequest(r, id)
if err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}

// Resolve labels
labels := make([]*IssueLabel, 0, len(issue.LabelIDs))
for _, labelID := range issue.LabelIDs {
if label, err := p.store.GetLabel(labelID); err == nil {
labels = append(labels, label)
}
}

// Resolve assignee name
var assigneeName string
if issue.AssigneeID != "" {
if user, appErr := p.API.GetUser(issue.AssigneeID); appErr == nil {
assigneeName = user.Username
}
}

// Resolve cycle name
var cycleName string
if issue.CycleID != "" {
if cycle, err := p.store.GetCycle(issue.CycleID); err == nil {
cycleName = cycle.Name
}
}

respondJSON(w, http.StatusOK, IssueContext{
Issue: issue,
Labels: labels,
AssigneeName: assigneeName,
CycleName: cycleName,
})
respondJSON(w, http.StatusOK, IssueContext{Issue: issue, Labels: labels, AssigneeName: assigneeName, CycleName: cycleName})
}
23 changes: 11 additions & 12 deletions mattermost-plugin-issues/server/api_cycles.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import (

func (p *Plugin) handleListCycles(w http.ResponseWriter, r *http.Request) {
projectID := mux.Vars(r)["id"]
if _, err := p.getProjectForRequest(r, projectID); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}
cycles, err := p.store.ListCycles(projectID)
if err != nil {
respondError(w, http.StatusInternalServerError, err.Error())
Expand All @@ -22,22 +26,18 @@ func (p *Plugin) handleListCycles(w http.ResponseWriter, r *http.Request) {

func (p *Plugin) handleCreateCycle(w http.ResponseWriter, r *http.Request) {
projectID := mux.Vars(r)["id"]
if _, err := p.getProjectForRequest(r, projectID); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}

var req CreateCycleRequest
if err := decodeJSON(r, &req); err != nil {
respondError(w, http.StatusBadRequest, "invalid request body")
return
}

cycle := &Cycle{
ID: uuid.New().String(),
ProjectID: projectID,
Name: req.Name,
StartDate: req.StartDate,
EndDate: req.EndDate,
IsActive: false,
}

cycle := &Cycle{ID: uuid.New().String(), ProjectID: projectID, Name: req.Name, StartDate: req.StartDate, EndDate: req.EndDate, IsActive: false}
if err := cycle.IsValid(); err != nil {
respondError(w, http.StatusBadRequest, err.Error())
return
Expand All @@ -55,7 +55,7 @@ func (p *Plugin) handleCreateCycle(w http.ResponseWriter, r *http.Request) {
func (p *Plugin) handleUpdateCycle(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

cycle, err := p.store.GetCycle(id)
cycle, err := p.getCycleForRequest(r, id)
if err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
Expand Down Expand Up @@ -96,8 +96,7 @@ func (p *Plugin) handleUpdateCycle(w http.ResponseWriter, r *http.Request) {

func (p *Plugin) handleDeleteCycle(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

if _, err := p.store.GetCycle(id); err != nil {
if _, err := p.getCycleForRequest(r, id); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}
Expand Down
23 changes: 13 additions & 10 deletions mattermost-plugin-issues/server/api_issues.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ import (

func (p *Plugin) handleListIssues(w http.ResponseWriter, r *http.Request) {
projectID := mux.Vars(r)["id"]
q := r.URL.Query()
if _, err := p.getProjectForRequest(r, projectID); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}

q := r.URL.Query()
params := IssueFilterParams{
Status: q.Get("status"),
Priority: q.Get("priority"),
Expand All @@ -28,14 +32,15 @@ func (p *Plugin) handleListIssues(w http.ResponseWriter, r *http.Request) {
return
}

respondJSON(w, http.StatusOK, IssueListResponse{
Issues: issues,
TotalCount: len(issues),
})
respondJSON(w, http.StatusOK, IssueListResponse{Issues: issues, TotalCount: len(issues)})
}

func (p *Plugin) handleCreateIssue(w http.ResponseWriter, r *http.Request) {
projectID := mux.Vars(r)["id"]
if _, err := p.getProjectForRequest(r, projectID); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}

var req CreateIssueRequest
if err := decodeJSON(r, &req); err != nil {
Expand Down Expand Up @@ -90,7 +95,7 @@ func (p *Plugin) handleCreateIssue(w http.ResponseWriter, r *http.Request) {

func (p *Plugin) handleGetIssue(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
issue, err := p.store.GetIssue(id)
issue, err := p.getIssueForRequest(r, id)
if err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
Expand All @@ -101,7 +106,7 @@ func (p *Plugin) handleGetIssue(w http.ResponseWriter, r *http.Request) {
func (p *Plugin) handleUpdateIssue(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

issue, err := p.store.GetIssue(id)
issue, err := p.getIssueForRequest(r, id)
if err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
Expand All @@ -122,7 +127,6 @@ func (p *Plugin) handleUpdateIssue(w http.ResponseWriter, r *http.Request) {
if req.Status != nil {
oldStatus := issue.Status
issue.Status = *req.Status
// Track completion time.
if !oldStatus.IsCompleted() && issue.Status.IsCompleted() {
issue.CompletedAt = nowMillis()
} else if oldStatus.IsCompleted() && !issue.Status.IsCompleted() {
Expand Down Expand Up @@ -167,13 +171,12 @@ func (p *Plugin) handleUpdateIssue(w http.ResponseWriter, r *http.Request) {
func (p *Plugin) handleDeleteIssue(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

issue, err := p.store.GetIssue(id)
issue, err := p.getIssueForRequest(r, id)
if err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}

// Only creator or sysadmin can delete.
userID := getUserID(r)
if issue.CreatedBy != userID {
user, appErr := p.API.GetUser(userID)
Expand Down
21 changes: 11 additions & 10 deletions mattermost-plugin-issues/server/api_labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import (

func (p *Plugin) handleListLabels(w http.ResponseWriter, r *http.Request) {
projectID := mux.Vars(r)["id"]
if _, err := p.getProjectForRequest(r, projectID); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}
labels, err := p.store.ListLabels(projectID)
if err != nil {
respondError(w, http.StatusInternalServerError, err.Error())
Expand All @@ -22,20 +26,18 @@ func (p *Plugin) handleListLabels(w http.ResponseWriter, r *http.Request) {

func (p *Plugin) handleCreateLabel(w http.ResponseWriter, r *http.Request) {
projectID := mux.Vars(r)["id"]
if _, err := p.getProjectForRequest(r, projectID); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}

var req CreateLabelRequest
if err := decodeJSON(r, &req); err != nil {
respondError(w, http.StatusBadRequest, "invalid request body")
return
}

label := &IssueLabel{
ID: uuid.New().String(),
ProjectID: projectID,
Name: req.Name,
Color: req.Color,
}

label := &IssueLabel{ID: uuid.New().String(), ProjectID: projectID, Name: req.Name, Color: req.Color}
if err := label.IsValid(); err != nil {
respondError(w, http.StatusBadRequest, err.Error())
return
Expand All @@ -53,7 +55,7 @@ func (p *Plugin) handleCreateLabel(w http.ResponseWriter, r *http.Request) {
func (p *Plugin) handleUpdateLabel(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

label, err := p.store.GetLabel(id)
label, err := p.getLabelForRequest(r, id)
if err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
Expand Down Expand Up @@ -88,8 +90,7 @@ func (p *Plugin) handleUpdateLabel(w http.ResponseWriter, r *http.Request) {

func (p *Plugin) handleDeleteLabel(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

if _, err := p.store.GetLabel(id); err != nil {
if _, err := p.getLabelForRequest(r, id); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}
Expand Down
11 changes: 6 additions & 5 deletions mattermost-plugin-issues/server/api_projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"github.com/gorilla/mux"
)

func (p *Plugin) handleListProjects(w http.ResponseWriter, _ *http.Request) {
projects, err := p.store.ListProjects()
func (p *Plugin) handleListProjects(w http.ResponseWriter, r *http.Request) {
projects, err := p.listProjectsForRequest(r)
if err != nil {
respondError(w, http.StatusInternalServerError, err.Error())
return
Expand All @@ -30,6 +30,7 @@ func (p *Plugin) handleCreateProject(w http.ResponseWriter, r *http.Request) {
ID: uuid.New().String(),
Name: req.Name,
Prefix: normalizePrefix(req.Prefix),
Scope: projectScopeFromRequest(r),
NextIssueNumber: 0,
CreatedBy: getUserID(r),
CreatedAt: nowMillis(),
Expand All @@ -50,7 +51,7 @@ func (p *Plugin) handleCreateProject(w http.ResponseWriter, r *http.Request) {

func (p *Plugin) handleGetProject(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
project, err := p.store.GetProject(id)
project, err := p.getProjectForRequest(r, id)
if err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
Expand All @@ -61,7 +62,7 @@ func (p *Plugin) handleGetProject(w http.ResponseWriter, r *http.Request) {
func (p *Plugin) handleUpdateProject(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

project, err := p.store.GetProject(id)
project, err := p.getProjectForRequest(r, id)
if err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
Expand Down Expand Up @@ -96,7 +97,7 @@ func (p *Plugin) handleUpdateProject(w http.ResponseWriter, r *http.Request) {
func (p *Plugin) handleDeleteProject(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

if _, err := p.store.GetProject(id); err != nil {
if _, err := p.getProjectForRequest(r, id); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}
Expand Down
13 changes: 12 additions & 1 deletion mattermost-plugin-issues/server/api_search.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ func (p *Plugin) handleGetIssueByIdentifier(w http.ResponseWriter, r *http.Reque
respondError(w, http.StatusNotFound, err.Error())
return
}
if _, err := p.getProjectForRequest(r, issue.ProjectID); err != nil {
respondError(w, http.StatusNotFound, err.Error())
return
}
respondJSON(w, http.StatusOK, issue)
}

Expand All @@ -38,5 +42,12 @@ func (p *Plugin) handleSearchAllIssues(w http.ResponseWriter, r *http.Request) {
respondError(w, http.StatusInternalServerError, err.Error())
return
}
respondJSON(w, http.StatusOK, issues)

filtered := make([]*Issue, 0, len(issues))
for _, issue := range issues {
if _, err := p.getProjectForRequest(r, issue.ProjectID); err == nil {
filtered = append(filtered, issue)
}
}
respondJSON(w, http.StatusOK, filtered)
}
Loading
Loading