From f8e7a2133d96cea1deb0ed2b304ccdd3b540a6de Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Fri, 26 Apr 2019 11:46:33 +0200 Subject: [PATCH] Add status stubs --- api/messaging/spec.json | 49 +++++++++ api/messaging/spec/status.json | 53 ++++++++++ docs/messaging/README.md | 55 ++++++++++ messaging/rest/handlers/status.go | 76 ++++++++++++++ messaging/rest/request/status.go | 167 ++++++++++++++++++++++++++++++ messaging/rest/status.go | 31 ++++++ 6 files changed, 431 insertions(+) create mode 100644 api/messaging/spec/status.json create mode 100644 messaging/rest/handlers/status.go create mode 100644 messaging/rest/request/status.go create mode 100644 messaging/rest/status.go diff --git a/api/messaging/spec.json b/api/messaging/spec.json index 5b56d275f..29fc0dec3 100644 --- a/api/messaging/spec.json +++ b/api/messaging/spec.json @@ -39,6 +39,55 @@ } ] }, + { + "title": "Status", + "parameters": {}, + "entrypoint": "status", + "path": "/status", + "authentication": [], + "apis": [ + { + "name": "list", + "path": "/", + "method": "GET", + "title": "See all current statuses" + }, + { + "name": "set", + "path": "/", + "method": "POST", + "title": "Set user's status", + "parameters": { + "post": [ + { + "type": "string", + "name": "icon", + "required": false, + "title": "Status icon" + }, + { + "type": "string", + "name": "message", + "required": false, + "title": "Status message" + }, + { + "type": "string", + "name": "expires", + "required": false, + "title": "Clear status when it expires (eg: when-active, afternoon, tomorrow 1h, 30m, 1 PM, 2019-05-20)" + } + ] + } + }, + { + "name": "delete", + "path": "/", + "method": "DELETE", + "title": "Clear status" + } + ] + }, { "title": "Channels", "description": "A channel is a representation of a sequence of messages. It has meta data like channel subject. Channels may be public, private or group.", diff --git a/api/messaging/spec/status.json b/api/messaging/spec/status.json new file mode 100644 index 000000000..d7319b9b0 --- /dev/null +++ b/api/messaging/spec/status.json @@ -0,0 +1,53 @@ +{ + "Title": "Status", + "Interface": "Status", + "Struct": null, + "Parameters": {}, + "Protocol": "", + "Authentication": [], + "Path": "/status", + "APIs": [ + { + "Name": "list", + "Method": "GET", + "Title": "See all current statuses", + "Path": "/", + "Parameters": null + }, + { + "Name": "set", + "Method": "POST", + "Title": "Set user's status", + "Path": "/", + "Parameters": { + "post": [ + { + "name": "icon", + "required": false, + "title": "Status icon", + "type": "string" + }, + { + "name": "message", + "required": false, + "title": "Status message", + "type": "string" + }, + { + "name": "expires", + "required": false, + "title": "Clear status when it expires (eg: when-active, afternoon, tomorrow 1h, 30m, 1 PM, 2019-05-20)", + "type": "string" + } + ] + } + }, + { + "Name": "delete", + "Method": "DELETE", + "Title": "Clear status", + "Path": "/", + "Parameters": null + } + ] +} \ No newline at end of file diff --git a/docs/messaging/README.md b/docs/messaging/README.md index cd1a4964f..7c9037f07 100644 --- a/docs/messaging/README.md +++ b/docs/messaging/README.md @@ -560,4 +560,59 @@ The following event types may be sent with a message event: | limit | uint | GET | Max number of messages | N/A | NO | | query | string | GET | Search query | N/A | NO | +--- + + + + +# Status + +| Method | Endpoint | Purpose | +| ------ | -------- | ------- | +| `GET` | `/status/` | See all current statuses | +| `POST` | `/status/` | Set user's status | +| `DELETE` | `/status/` | Clear status | + +## See all current statuses + +#### Method + +| URI | Protocol | Method | Authentication | +| --- | -------- | ------ | -------------- | +| `/status/` | HTTP/S | GET | | + +#### Request parameters + +| Parameter | Type | Method | Description | Default | Required? | +| --------- | ---- | ------ | ----------- | ------- | --------- | + +## Set user's status + +#### Method + +| URI | Protocol | Method | Authentication | +| --- | -------- | ------ | -------------- | +| `/status/` | HTTP/S | POST | | + +#### Request parameters + +| Parameter | Type | Method | Description | Default | Required? | +| --------- | ---- | ------ | ----------- | ------- | --------- | +| icon | string | POST | Status icon | N/A | NO | +| message | string | POST | Status message | N/A | NO | +| expires | string | POST | Clear status when it expires (eg: when-active, afternoon, tomorrow 1h, 30m, 1 PM, 2019-05-20) | N/A | NO | + +## Clear status + +#### Method + +| URI | Protocol | Method | Authentication | +| --- | -------- | ------ | -------------- | +| `/status/` | HTTP/S | DELETE | | + +#### Request parameters + +| Parameter | Type | Method | Description | Default | Required? | +| --------- | ---- | ------ | ----------- | ------- | --------- | + --- \ No newline at end of file diff --git a/messaging/rest/handlers/status.go b/messaging/rest/handlers/status.go new file mode 100644 index 000000000..a9c2cb1ba --- /dev/null +++ b/messaging/rest/handlers/status.go @@ -0,0 +1,76 @@ +package handlers + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `status.go`, `status.util.go` or `status_test.go` to + implement your API calls, helper functions and tests. The file `status.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "context" + + "net/http" + + "github.com/go-chi/chi" + "github.com/titpetric/factory/resputil" + + "github.com/crusttech/crust/messaging/rest/request" +) + +// Internal API interface +type StatusAPI interface { + List(context.Context, *request.StatusList) (interface{}, error) + Set(context.Context, *request.StatusSet) (interface{}, error) + Delete(context.Context, *request.StatusDelete) (interface{}, error) +} + +// HTTP API interface +type Status struct { + List func(http.ResponseWriter, *http.Request) + Set func(http.ResponseWriter, *http.Request) + Delete func(http.ResponseWriter, *http.Request) +} + +func NewStatus(sh StatusAPI) *Status { + return &Status{ + List: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewStatusList() + resputil.JSON(w, params.Fill(r), func() (interface{}, error) { + return sh.List(r.Context(), params) + }) + }, + Set: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewStatusSet() + resputil.JSON(w, params.Fill(r), func() (interface{}, error) { + return sh.Set(r.Context(), params) + }) + }, + Delete: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewStatusDelete() + resputil.JSON(w, params.Fill(r), func() (interface{}, error) { + return sh.Delete(r.Context(), params) + }) + }, + } +} + +func (sh *Status) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) { + r.Group(func(r chi.Router) { + r.Use(middlewares...) + r.Get("/status/", sh.List) + r.Post("/status/", sh.Set) + r.Delete("/status/", sh.Delete) + }) +} diff --git a/messaging/rest/request/status.go b/messaging/rest/request/status.go new file mode 100644 index 000000000..cf3ac946e --- /dev/null +++ b/messaging/rest/request/status.go @@ -0,0 +1,167 @@ +package request + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `status.go`, `status.util.go` or `status_test.go` to + implement your API calls, helper functions and tests. The file `status.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "io" + "strings" + + "encoding/json" + "mime/multipart" + "net/http" + + "github.com/go-chi/chi" + "github.com/pkg/errors" +) + +var _ = chi.URLParam +var _ = multipart.FileHeader{} + +// Status list request parameters +type StatusList struct { +} + +func NewStatusList() *StatusList { + return &StatusList{} +} + +func (sReq *StatusList) Fill(r *http.Request) (err error) { + if strings.ToLower(r.Header.Get("content-type")) == "application/json" { + err = json.NewDecoder(r.Body).Decode(sReq) + + switch { + case err == io.EOF: + err = nil + case err != nil: + return errors.Wrap(err, "error parsing http request body") + } + } + + if err = r.ParseForm(); err != nil { + return err + } + + get := map[string]string{} + post := map[string]string{} + urlQuery := r.URL.Query() + for name, param := range urlQuery { + get[name] = string(param[0]) + } + postVars := r.Form + for name, param := range postVars { + post[name] = string(param[0]) + } + + return err +} + +var _ RequestFiller = NewStatusList() + +// Status set request parameters +type StatusSet struct { + Icon string + Message string + Expires string +} + +func NewStatusSet() *StatusSet { + return &StatusSet{} +} + +func (sReq *StatusSet) Fill(r *http.Request) (err error) { + if strings.ToLower(r.Header.Get("content-type")) == "application/json" { + err = json.NewDecoder(r.Body).Decode(sReq) + + switch { + case err == io.EOF: + err = nil + case err != nil: + return errors.Wrap(err, "error parsing http request body") + } + } + + if err = r.ParseForm(); err != nil { + return err + } + + get := map[string]string{} + post := map[string]string{} + urlQuery := r.URL.Query() + for name, param := range urlQuery { + get[name] = string(param[0]) + } + postVars := r.Form + for name, param := range postVars { + post[name] = string(param[0]) + } + + if val, ok := post["icon"]; ok { + + sReq.Icon = val + } + if val, ok := post["message"]; ok { + + sReq.Message = val + } + if val, ok := post["expires"]; ok { + + sReq.Expires = val + } + + return err +} + +var _ RequestFiller = NewStatusSet() + +// Status delete request parameters +type StatusDelete struct { +} + +func NewStatusDelete() *StatusDelete { + return &StatusDelete{} +} + +func (sReq *StatusDelete) Fill(r *http.Request) (err error) { + if strings.ToLower(r.Header.Get("content-type")) == "application/json" { + err = json.NewDecoder(r.Body).Decode(sReq) + + switch { + case err == io.EOF: + err = nil + case err != nil: + return errors.Wrap(err, "error parsing http request body") + } + } + + if err = r.ParseForm(); err != nil { + return err + } + + get := map[string]string{} + post := map[string]string{} + urlQuery := r.URL.Query() + for name, param := range urlQuery { + get[name] = string(param[0]) + } + postVars := r.Form + for name, param := range postVars { + post[name] = string(param[0]) + } + + return err +} + +var _ RequestFiller = NewStatusDelete() diff --git a/messaging/rest/status.go b/messaging/rest/status.go new file mode 100644 index 000000000..95810b482 --- /dev/null +++ b/messaging/rest/status.go @@ -0,0 +1,31 @@ +package rest + +import ( + "context" + + "github.com/pkg/errors" + + "github.com/crusttech/crust/messaging/rest/request" +) + +var _ = errors.Wrap + +type Status struct { + // xxx service.XXXService +} + +func (Status) New() *Status { + return &Status{} +} + +func (ctrl *Status) List(ctx context.Context, r *request.StatusList) (interface{}, error) { + return nil, errors.New("Not implemented: Status.list") +} + +func (ctrl *Status) Set(ctx context.Context, r *request.StatusSet) (interface{}, error) { + return nil, errors.New("Not implemented: Status.set") +} + +func (ctrl *Status) Delete(ctx context.Context, r *request.StatusDelete) (interface{}, error) { + return nil, errors.New("Not implemented: Status.delete") +}