diff options
| -rwxr-xr-x | build.sh | 10 | ||||
| -rw-r--r-- | docs/docs.go | 182 | ||||
| -rw-r--r-- | docs/swagger.json | 158 | ||||
| -rw-r--r-- | docs/swagger.yaml | 108 | ||||
| -rw-r--r-- | go.mod | 13 | ||||
| -rw-r--r-- | go.sum | 54 | ||||
| -rw-r--r-- | main.go | 129 |
7 files changed, 648 insertions, 6 deletions
@@ -16,9 +16,13 @@ if ! git diff-index --quiet HEAD ; then version="dirty: $version" fi -cd ui -npm run build -cd .. +# cd ui +# npm install +# npm run build +# cd .. + +go install github.com/swaggo/swag/cmd/swag@latest +swag init export CGO_ENABLED=0 diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..95e9128 --- /dev/null +++ b/docs/docs.go @@ -0,0 +1,182 @@ +// Package docs GENERATED BY SWAG; DO NOT EDIT +// This file was generated by swaggo/swag +package docs + +import "github.com/swaggo/swag" + +const docTemplate = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": { + "name": "Mitchell Riedstra", + "url": "https://riedstra.dev", + "email": "mitch@riedstra.dev" + }, + "license": { + "name": "ISC" + }, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/v0/del/{id}": { + "delete": { + "description": "Remove a paste from the filesystem", + "produces": [ + "text/plain" + ], + "tags": [ + "v0" + ], + "summary": "Deletes a paste for a given ID", + "parameters": [ + { + "type": "string", + "description": "Paste ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, + "/v0/view/{id}": { + "get": { + "description": "Fetches the contents of a paste if given an ID", + "produces": [ + "text/plain" + ], + "tags": [ + "v0" + ], + "summary": "View a paste for a given ID", + "parameters": [ + { + "type": "string", + "description": "Paste ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, + "/v1/del/{id}": { + "delete": { + "description": "Remove a paste from the filesystem", + "produces": [ + "application/json" + ], + "tags": [ + "v1" + ], + "summary": "Deletes a paste for a given ID", + "parameters": [ + { + "type": "string", + "description": "Paste ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, + "/v1/getToken": { + "post": { + "description": "Returns an API key that's valid for a pre-determined amount of hours", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "v1" + ], + "summary": "Get an API key with valid credentials", + "parameters": [ + { + "description": "User Credentials", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/main.Credentials" + } + } + ], + "responses": {} + } + }, + "/v1/view/{id}": { + "get": { + "description": "Fetches the contents of a paste if given an ID", + "produces": [ + "application/json" + ], + "tags": [ + "v1" + ], + "summary": "View a paste for a given ID", + "parameters": [ + { + "type": "string", + "description": "Paste ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + } + }, + "definitions": { + "main.Credentials": { + "description": "User's credentials", + "type": "object", + "properties": { + "Password": { + "type": "string" + }, + "Username": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + }, + "BasicAuth": { + "type": "basic" + } + } +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "1.0", + Host: "", + BasePath: "/api", + Schemes: []string{}, + Title: "Simple Pastebin API", + Description: "User's credentials", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..27c60a0 --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,158 @@ +{ + "swagger": "2.0", + "info": { + "description": "User's credentials", + "title": "Simple Pastebin API", + "contact": { + "name": "Mitchell Riedstra", + "url": "https://riedstra.dev", + "email": "mitch@riedstra.dev" + }, + "license": { + "name": "ISC" + }, + "version": "1.0" + }, + "basePath": "/api", + "paths": { + "/v0/del/{id}": { + "delete": { + "description": "Remove a paste from the filesystem", + "produces": [ + "text/plain" + ], + "tags": [ + "v0" + ], + "summary": "Deletes a paste for a given ID", + "parameters": [ + { + "type": "string", + "description": "Paste ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, + "/v0/view/{id}": { + "get": { + "description": "Fetches the contents of a paste if given an ID", + "produces": [ + "text/plain" + ], + "tags": [ + "v0" + ], + "summary": "View a paste for a given ID", + "parameters": [ + { + "type": "string", + "description": "Paste ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, + "/v1/del/{id}": { + "delete": { + "description": "Remove a paste from the filesystem", + "produces": [ + "application/json" + ], + "tags": [ + "v1" + ], + "summary": "Deletes a paste for a given ID", + "parameters": [ + { + "type": "string", + "description": "Paste ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, + "/v1/getToken": { + "post": { + "description": "Returns an API key that's valid for a pre-determined amount of hours", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "v1" + ], + "summary": "Get an API key with valid credentials", + "parameters": [ + { + "description": "User Credentials", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/main.Credentials" + } + } + ], + "responses": {} + } + }, + "/v1/view/{id}": { + "get": { + "description": "Fetches the contents of a paste if given an ID", + "produces": [ + "application/json" + ], + "tags": [ + "v1" + ], + "summary": "View a paste for a given ID", + "parameters": [ + { + "type": "string", + "description": "Paste ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + } + }, + "definitions": { + "main.Credentials": { + "description": "User's credentials", + "type": "object", + "properties": { + "Password": { + "type": "string" + }, + "Username": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + }, + "BasicAuth": { + "type": "basic" + } + } +}
\ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..bcff994 --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,108 @@ +basePath: /api +definitions: + main.Credentials: + description: User's credentials + properties: + Password: + type: string + Username: + type: string + type: object +info: + contact: + email: mitch@riedstra.dev + name: Mitchell Riedstra + url: https://riedstra.dev + description: User's credentials + license: + name: ISC + title: Simple Pastebin API + version: "1.0" +paths: + /v0/del/{id}: + delete: + description: Remove a paste from the filesystem + parameters: + - description: Paste ID + in: path + name: id + required: true + type: string + produces: + - text/plain + responses: {} + summary: Deletes a paste for a given ID + tags: + - v0 + /v0/view/{id}: + get: + description: Fetches the contents of a paste if given an ID + parameters: + - description: Paste ID + in: path + name: id + required: true + type: string + produces: + - text/plain + responses: {} + summary: View a paste for a given ID + tags: + - v0 + /v1/del/{id}: + delete: + description: Remove a paste from the filesystem + parameters: + - description: Paste ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: {} + summary: Deletes a paste for a given ID + tags: + - v1 + /v1/getToken: + post: + consumes: + - application/json + description: Returns an API key that's valid for a pre-determined amount of + hours + parameters: + - description: User Credentials + in: body + name: request + required: true + schema: + $ref: '#/definitions/main.Credentials' + produces: + - application/json + responses: {} + summary: Get an API key with valid credentials + tags: + - v1 + /v1/view/{id}: + get: + description: Fetches the contents of a paste if given an ID + parameters: + - description: Paste ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: {} + summary: View a paste for a given ID + tags: + - v1 +securityDefinitions: + "": + in: header + name: Authorization + type: apiKey + BasicAuth: + type: basic +swagger: "2.0" @@ -8,6 +8,19 @@ require ( ) require ( + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/spec v0.20.6 // indirect + github.com/go-openapi/swag v0.19.15 // indirect github.com/golang-jwt/jwt/v4 v4.4.3 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect + github.com/swaggo/http-swagger v1.3.3 // indirect + github.com/swaggo/swag v1.8.1 // indirect + golang.org/x/net v0.3.0 // indirect golang.org/x/sys v0.3.0 // indirect + golang.org/x/tools v0.1.10 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect ) @@ -1,8 +1,62 @@ +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ= +github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU= github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe h1:K8pHPVoTgxFJt1lXuIzzOX7zZhZFldJQK/CgKx9BFIc= +github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= +github.com/swaggo/http-swagger v1.3.3 h1:Hu5Z0L9ssyBLofaama21iYaF2VbWyA8jdohaaCGpHsc= +github.com/swaggo/http-swagger v1.3.3/go.mod h1:sE+4PjD89IxMPm77FnkDz0sdO+p5lbXzrVWT6OTVVGo= +github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI= +github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -25,6 +25,9 @@ import ( jwt "github.com/golang-jwt/jwt/v4" "golang.org/x/crypto/bcrypt" "golang.org/x/term" + + httpSwagger "github.com/swaggo/http-swagger" + _ "riedstra.dev/mitch/paste/docs" ) // Default to the system umask @@ -69,6 +72,20 @@ type Response struct { Data any `json:",omitempty"` } +// @title Simple Pastebin API +// @version 1.0 +// @description Simple pastebin backed by your filesystem +// @contact.name Mitchell Riedstra +// @contact.url https://riedstra.dev +// @contact.email mitch@riedstra.dev +// @license.name ISC +// @BasePath /api +// +// @securityDefinitions.basic BasicAuth +// @securitydefinitions.apikey +// @in header +// @name Authorization +// @tokenURL /v1/login func main() { var ( listen = ":6130" @@ -297,9 +314,14 @@ func (a *App) Handler() http.Handler { "/api/v0/view/", a.HandleViewPlain()), + "/api/v1/getToken": tokenHandler(a.users, a.jwtKey, a.sessionHours), "/api/v1/login": loginHandler(a.users, a.jwtKey, a.sessionHours), "/api/v1/logout": logoutHandler(), + "/swagger/": httpSwagger.Handler( + httpSwagger.URL("/swagger/doc.json"), + ), + "/_app/": http.FileServer(http.FS(a.static)), "/": a.HandleIndex(a.static), } @@ -392,8 +414,8 @@ func genTokenKey() string { // encoding the response status code in the header, JSON, and a friendly // message as well as any other exported members of the Response struct. func sendJSON(er Response) { - er.w.WriteHeader(er.Code) er.w.Header().Add("Content-type", "application/json") + er.w.WriteHeader(er.Code) enc := json.NewEncoder(er.w) enc.SetIndent("", " ") _ = enc.Encode(er) @@ -403,8 +425,8 @@ func sendJSON(er Response) { // output verbatim unless the rdr is not nil, in which case the rdr // is used instead func sendPlain(r Response, rdr io.Reader) { + r.w.Header().Add("Content-type", "text/plain") r.w.WriteHeader(r.Code) - r.w.Header().Add("Content-type", "application/json") if rdr != nil { _, _ = io.Copy(r.w, rdr) } else { @@ -532,6 +554,66 @@ func (users UsersMap) AuthHandler(next http.Handler, jwtKey string, }) } +// Credentials +// +// @Description User's credentials +type Credentials struct { + Username string `json:"Username"` + Password string `json:"Password"` +} + +// tokenHandler +// +// @Summary Get an API key with valid credentials +// @Description Returns an API key that's valid for a pre-determined amount of hours +// @Tags v1 +// @Produce json +// @Accept json +// @Param request body Credentials true "User Credentials" +// @Router /v1/getToken [post] +func tokenHandler(users UsersMap, jwtKey string, sessionHours int, +) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != "POST" { + sendJSON(Response{w, http.StatusBadRequest, + "Invalid type. POST only", nil}) + return + } + + dec := json.NewDecoder(r.Body) + in := &Credentials{} + + err := dec.Decode(in) + if err != nil { + sendJSON(Response{w, http.StatusBadRequest, "Invalid request", nil}) + return + } + + if !users.IsValidLogin(in.Username, in.Password) { + sendJSON(Response{w, http.StatusUnauthorized, + "Invalid username or password", nil}) + return + } + expires := time.Now().Add(time.Hour * time.Duration(sessionHours)) + + claims := &jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(expires), + ID: in.Username, + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS512, claims) + ss, err := token.SignedString([]byte(jwtKey)) + if err != nil { + sendJSON(Response{w, http.StatusInternalServerError, + "Invalid username or password", nil}) + return + } + + sendJSON(Response{w, http.StatusOK, "Ok", + struct{ Token string } { ss }}) + }) +} + func loginHandler(users UsersMap, jwtKey string, sessionHours int, ) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -665,6 +747,14 @@ func getPastePathFromRawURL(storage, u string) string { filepath.Clean(u), "/", "")) } +// HandleViewJSON +// +// @Summary View a paste for a given ID +// @Description Fetches the contents of a paste if given an ID +// @Tags v1 +// @Produce json +// @Param id path string true "Paste ID" +// @Router /v1/view/{id} [get] func (a *App) HandleViewJSON() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { pth := getPastePathFromRawURL(a.storage, r.URL.Path) @@ -688,6 +778,14 @@ func (a *App) HandleViewJSON() http.Handler { }) } +// HandleViewPlain +// +// @Summary View a paste for a given ID +// @Description Fetches the contents of a paste if given an ID +// @Tags v0 +// @Produce text/plain +// @Param id path string true "Paste ID" +// @Router /v0/view/{id} [get] func (a *App) HandleViewPlain() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { pth := getPastePathFromRawURL(a.storage, r.URL.Path) @@ -703,6 +801,16 @@ func (a *App) HandleViewPlain() http.Handler { }) } +// HandleDel +// +// @Summary Deletes a paste for a given ID +// @Description Remove a paste from the filesystem +// @Tags v0 +// @Produce text/plain +// @Param id path string true "Paste ID" +// @Router /v0/del/{id} [delete] +// @securityDefinitions.basic BasicAuth +// @securityDefinitions.apikey ApiKeyAuth func (a *App) HandleDel() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { pth := getPastePathFromRawURL(a.storage, r.URL.Path) @@ -724,9 +832,24 @@ func (a *App) HandleDel() http.Handler { }) } +// HandleDelJSON +// +// @Summary Deletes a paste for a given ID +// @Description Remove a paste from the filesystem +// @Tags v1 +// @Produce application/json +// @Param id path string true "Paste ID" +// @Router /v1/del/{id} [delete] +// @securityDefinitions.basic BasicAuth +// @name Authorization func (a *App) HandleDelJSON() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - logger.Println("Made it to delete...") + if r.Method != "DELETE" { + sendJSON(Response{w, http.StatusMethodNotAllowed, + "Method not allowed", nil}) + return + } + pth := getPastePathFromRawURL(a.storage, r.URL.Path) logger.Println("Deleting path: ", pth) err := os.Remove(pth) |
