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
82 changes: 79 additions & 3 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 @@ -98,7 +102,7 @@ func (h *Handler) setLink(w http.ResponseWriter, r *http.Request) {
found := false
changed := false
for i := range links {
if links[i].Name == newLink.Name || links[i].Pattern == newLink.Pattern {
if links[i].Name == newLink.Name {
if !links[i].Equals(newLink) {
links[i] = newLink
changed = true
Expand All @@ -114,12 +118,84 @@ 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 should not be empty"))
return
}

links := h.store.GetLinks()
found := false
for i := 0; i < len(links); i++ {
if links[i].Name == autolinkName {
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
break
}
}

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
}

var autolink *autolink.Autolink
for _, link := range links {
if link.Name == autolinkName {
autolink = &link
break
}
}
if autolink == nil {
h.handleError(w, errors.Errorf("no autolink found with name %s", autolinkName))
return
}

h.handleSendingJSONContent(w, autolink)
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
72 changes: 68 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,22 +49,82 @@ 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
}
defer resp.Body.Close()

resp, err := c.Do(req)
if resp.StatusCode != http.StatusOK {
respBody, _ := ioutil.ReadAll(resp.Body)
return fmt.Errorf("unable to add the link %s. Error: %v, %v", link.Name, resp.StatusCode, string(respBody))
}
}

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)
return fmt.Errorf("unable to install autolink. Error: %v, %v", resp.StatusCode, string(respBody))
return fmt.Errorf("unable to delete the link %s. Error: %v, %v", link, resp.StatusCode, string(respBody))
}
}

return nil
}

func (c *Client) Get(autolinkName string) (*autolink.Autolink, error) {
queryParams := url.Values{
AutolinkNameQueryParam: {autolinkName},
}

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

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 get the link %s. Error: %v, %v", autolinkName, resp.StatusCode, string(respBody))
}

var response *autolink.Autolink
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
}

return resp, nil
}