Skip to content
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

[GH-207] Added CRUD operations in autolink plugin #213

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
81 changes: 79 additions & 2 deletions server/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/pkg/errors"

"github.com/mattermost/mattermost-plugin-autolink/server/autolink"
"github.com/mattermost/mattermost-plugin-autolink/server/autolinkclient"
)

type Store interface {
Expand All @@ -34,7 +35,10 @@ func NewHandler(store Store, authorization Authorization) *Handler {
root := mux.NewRouter()
api := root.PathPrefix("/api/v1").Subrouter()
api.Use(h.adminOrPluginRequired)
api.HandleFunc("/link", h.setLink).Methods("POST")
link := api.PathPrefix("/link").Subrouter()
link.HandleFunc("", h.setLink).Methods(http.MethodPost)
link.HandleFunc("", h.deleteLink).Methods(http.MethodDelete)
link.HandleFunc("", h.getLinks).Methods(http.MethodGet)

api.Handle("{anything:.*}", http.NotFoundHandler())

Expand Down Expand Up @@ -114,12 +118,85 @@ func (h *Handler) setLink(w http.ResponseWriter, r *http.Request) {
status := http.StatusNotModified
if changed {
if err := h.store.SaveLinks(links); err != nil {
h.handleError(w, errors.Wrap(err, "unable to save link"))
h.handleError(w, errors.Wrap(err, "unable to save the link"))
return
}
status = http.StatusOK
}

ReturnStatusOK(status, w)
}

func (h *Handler) deleteLink(w http.ResponseWriter, r *http.Request) {
autolinkName := r.URL.Query().Get(autolinkclient.AutolinkNameQueryParam)
if autolinkName == "" {
h.handleError(w, errors.New("autolink name or pattern should not be empty"))
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
return
}

links := h.store.GetLinks()
found := false
for i := 0; i < len(links); i++ {
if links[i].Name == autolinkName || links[i].Pattern == autolinkName {
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
links = append(links[:i], links[i+1:]...)
found = true
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
}
}

status := http.StatusNotModified
if found {
if err := h.store.SaveLinks(links); err != nil {
h.handleError(w, errors.Wrap(err, "unable to save the link"))
return
}
status = http.StatusOK
}

ReturnStatusOK(status, w)
}

func (h *Handler) getLinks(w http.ResponseWriter, r *http.Request) {
links := h.store.GetLinks()

autolinkName := r.URL.Query().Get(autolinkclient.AutolinkNameQueryParam)
if autolinkName == "" {
h.handleSendingJSONContent(w, links)
return
}

found := false
var autolinks []autolink.Autolink
for _, link := range links {
if link.Name == autolinkName || link.Pattern == autolinkName {
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
autolinks = append(autolinks, link)
found = true
}
}

if !found {
h.handleError(w, errors.Errorf("no autolink found with name or pattern %s", autolinkName))
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
return
}

h.handleSendingJSONContent(w, autolinks)
return
}

func (h *Handler) handleSendingJSONContent(w http.ResponseWriter, v interface{}) {
w.Header().Set("Content-Type", "application/json")
b, err := json.Marshal(v)
if err != nil {
h.handleError(w, errors.Wrap(err, "failed to marshal JSON response"))
return
}

if _, err = w.Write(b); err != nil {
h.handleError(w, errors.Wrap(err, "failed to write JSON response"))
return
}
}

func ReturnStatusOK(status int, w http.ResponseWriter) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
_, _ = w.Write([]byte(`{"status": "OK"}`))
Expand Down
70 changes: 66 additions & 4 deletions server/autolinkclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ import (
"fmt"
"io/ioutil"
"net/http"
"net/url"

"github.com/mattermost/mattermost-plugin-autolink/server/autolink"
)

const autolinkPluginID = "mattermost-autolink"
const (
autolinkPluginID = "mattermost-autolink"
AutolinkNameQueryParam = "autolinkName"
)

type PluginAPI interface {
PluginHTTP(*http.Request) *http.Response
Expand Down Expand Up @@ -45,16 +49,30 @@ func (c *Client) Add(links ...autolink.Autolink) error {
return err
}

req, err := http.NewRequest("POST", "/"+autolinkPluginID+"/api/v1/link", bytes.NewReader(linkBytes))
resp, err := c.call("/"+autolinkPluginID+"/api/v1/link", http.MethodPost, linkBytes, nil)
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}

resp, err := c.Do(req)
if resp.StatusCode != http.StatusOK {
respBody, _ := ioutil.ReadAll(resp.Body)
return fmt.Errorf("unable to install autolink. Error: %v, %v", resp.StatusCode, string(respBody))
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
}
}

return nil
}

func (c *Client) Delete(links ...string) error {
for _, link := range links {
queryParams := url.Values{
AutolinkNameQueryParam: {link},
}

resp, err := c.call("/"+autolinkPluginID+"/api/v1/link", http.MethodDelete, nil, queryParams)
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}
defer resp.Body.Close()
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved

if resp.StatusCode != http.StatusOK {
respBody, _ := ioutil.ReadAll(resp.Body)
Expand All @@ -64,3 +82,47 @@ func (c *Client) Add(links ...autolink.Autolink) error {

return nil
}

func (c *Client) Get(autolinkName string) ([]*autolink.Autolink, error) {
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
queryParams := url.Values{
AutolinkNameQueryParam: {autolinkName},
}

resp, err := c.call("/"+autolinkPluginID+"/api/v1/link", http.MethodGet, nil, queryParams)
if err != nil {
return nil, err
}

respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unable to install autolink. Error: %v, %v", resp.StatusCode, string(respBody))
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
}

var response []*autolink.Autolink
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
if err = json.Unmarshal(respBody, &response); err != nil {
return nil, err
}

return response, nil
}

func (c *Client) call(url, method string, body []byte, queryParams url.Values) (*http.Response, error) {
req, err := http.NewRequest(method, url, bytes.NewReader(body))
if err != nil {
return nil, err
}

req.URL.RawQuery = queryParams.Encode()

resp, err := c.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved

return resp, nil
}