github.com/decred/politeia@v1.4.0/politeiawww/api/http/v3/v3.go (about) 1 // Copyright (c) 2022 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package v3 6 7 import "fmt" 8 9 const ( 10 // APIVersion is the version of the API that this package represents. 11 APIVersion uint32 = 3 12 13 // APIVersionPrefix is prefixed onto all routes defined in this package. 14 APIVersionPrefix = "/v3" 15 16 // VersionRoute is a GET request route that returns the server version 17 // information and sets the CSRF tokens for the client. The VersionReply can 18 // be retrieved from both the "/" route and the "/v3/version" route. This 19 // allows clients to be able to determine version information without needing 20 // to have any prior knowledge of the API. 21 // 22 // This route sets CSRF tokens for clients using the double submit cookie 23 // technique. A token is set in a cookie and a token is set in a header. 24 // Clients MUST make a successful Version call before they'll be able to 25 // use CSRF protected routes. 26 // 27 // This route returns a VersionReply. 28 VersionRoute = "/version" 29 30 // PolicyRoute is a GET request route that returns the API policy 31 // information. 32 // 33 // This route returns a PolicyReply. 34 PolicyRoute = "/policy" 35 36 // NewUserRoute is a POST request route that executes a plugin command that 37 // creates a new user. This is the only route that can be used for plugin 38 // commands that result in a new user being created. 39 // 40 // This route is CSRF protected. Clients must obtain CSRF tokens from the 41 // Version route before they'll be able to use this route. A 403 is returned 42 // if the client attempts to use this route without the proper CSRF tokens. 43 // 44 // This route accepts a PluginCmd and returns a PluginReply. 45 NewUserRoute = "/newuser" 46 47 // WriteRoute is a POST request route that executes a plugin command that 48 // writes data to the backend. 49 // 50 // This route is CSRF protected. Clients must obtain CSRF tokens from the 51 // Version route before they'll be able to use this route. A 403 is returned 52 // if the client attempts to use this route without the proper CSRF tokens. 53 // 54 // This route accepts a PluginCmd and returns a PluginReply. 55 WriteRoute = "/write" 56 57 // ReadRoute is a POST request route that executes an individual read-only 58 // plugin command. This route is intended to be used for expensive plugin 59 // read commands that cannot be batched due to their memory or performance 60 // requirements. This allows the sysadmin to set different rate limiting 61 // constraints for expensive commands. 62 // 63 // This route accepts a PluginCmd and returns a PluginReply. 64 ReadRoute = "/read" 65 66 // ReadBatchRoute is a POST request route that executes a batch of read-only 67 // plugin commands. This route is intended to be used for inexpensive plugin 68 // commands that will not cause performance issues during the execution of 69 // large batches. 70 // 71 // This route accepts a Batch and returns a BatchReply. 72 ReadBatchRoute = "/readbatch" 73 ) 74 75 const ( 76 // CSRFTokenHeader is the header that will contain a CSRF token. 77 CSRFTokenHeader = "X-CSRF-Token" 78 79 // SessionCookieName is the cookie name for the session cookie. Clients will 80 // have the session cookie set the first time a plugin command route is hit. 81 SessionCookieName = "session" 82 ) 83 84 // Version contains the GET request parameters for the VersionRoute. The 85 // VersionRoute returns a VersionReply. 86 // 87 // This route sets CSRF tokens for clients using the double submit cookie 88 // technique. A token is set in a cookie and a token is set in a header. 89 // Clients MUST make a successful Version call before they'll be able to 90 // use CSRF protected routes. 91 type Version struct{} 92 93 // VersionReply is the reply for the VersionRoute. It contains the server 94 // version information and the list of plugins that the server is running. The 95 // client should verify compatibility with the server version and plugins. 96 type VersionReply struct { 97 // APIVersion is the lowest supported API version. 98 APIVersion uint32 `json:"apiversion"` 99 100 // BuildVersion is the sematic version of the server build. 101 BuildVersion string `json:"buildversion"` 102 103 // Plugins contains the plugin ID and lowest supported plugin API version 104 // for all registered plugins. 105 Plugins map[string]uint32 `json:"plugins"` // [pluginID]version 106 } 107 108 // Policy contains the GET request parameters for the PolicyRoute. The 109 // PolicyRoute returns a PolicyReply. 110 type Policy struct{} 111 112 // PolicyReply is the reply for the PolicyRoute. It contains API policy 113 // information. 114 type PolicyReply struct { 115 // ReadBatchLimit contains the maximum number of plugin commands allowed in 116 // a read batch request. 117 ReadBatchLimit uint32 `json:"readbatchlimit"` 118 } 119 120 // Cmd represents a plugin command. 121 type Cmd struct { 122 PluginID string `json:"pluginid"` 123 Version uint32 `json:"version"` // Plugin API version 124 Cmd string `json:"cmd"` 125 Payload string `json:"payload"` // Cmd payload, JSON encoded 126 } 127 128 // CmdReply is the reply to a Cmd request. 129 type CmdReply struct { 130 PluginID string `json:"pluginid"` 131 Version uint32 `json:"version"` // Plugin API version 132 Cmd string `json:"cmd"` 133 Payload string `json:"payload"` // Reply payload, JSON encoded 134 Error error `json:"error,omitempty"` 135 } 136 137 // Batch contains a batch of read-only plugin commands. 138 type Batch struct { 139 Cmds []Cmd `json:"cmds"` 140 } 141 142 // BatchReply is the reply to a Batch request. 143 type BatchReply struct { 144 Replies []CmdReply `json:"replies"` 145 } 146 147 // PluginError is returned when a plugin command encounters an error that was 148 // caused by the user (ex. malformed input, bad timing, etc). The HTTP status 149 // code will be 200 and the error will be returned in the Error field of the 150 // PluginReply. 151 type PluginError struct { 152 PluginID string `json:"pluginid"` 153 ErrorCode uint32 `json:"errorcode"` 154 ErrorContext string `json:"errorcontext,omitempty"` 155 } 156 157 // Error satisfies the error interface. 158 func (e PluginError) Error() string { 159 return fmt.Sprintf("%v plugin error code: %v", e.PluginID, e.ErrorCode) 160 } 161 162 // UserError is returned in the response body when the server encounters an 163 // error that is caused by something that the user did, such as a invalid 164 // request body, and the error occurred prior to execution of the plugin 165 // command. The HTTP status code will be 400. 166 type UserError struct { 167 ErrorCode ErrorCodeT `json:"errorcode"` 168 ErrorContext string `json:"errorcontext,omitempty"` 169 } 170 171 // Error satisfies the error interface. 172 func (e UserError) Error() string { 173 if e.ErrorContext == "" { 174 return fmt.Sprintf("user error (%v): %v", 175 e.ErrorCode, ErrorCodes[e.ErrorCode]) 176 } 177 return fmt.Sprintf("user error (%v): %v, %v", 178 e.ErrorCode, ErrorCodes[e.ErrorCode], e.ErrorContext) 179 } 180 181 // ErrorCodeT represents a user error code. 182 type ErrorCodeT uint32 183 184 const ( 185 // ErrorCodeInvalid is an invalid error code. 186 ErrorCodeInvalid ErrorCodeT = 0 187 188 // ErrorCodeInvalidInput is returned when the request body could not be 189 // parsed. 190 ErrorCodeInvalidInput ErrorCodeT = 1 191 192 // ErrorCodePluginNotFound is returned when a plugin ID is provided that 193 // does not correspond to a registered plugin. 194 ErrorCodePluginNotFound ErrorCodeT = 2 195 196 // ErrorCodePluginNotAuthorized is returned when a plugin is attempting to 197 // execute a command using a route that it is not authorized to use. 198 ErrorCodePluginNotAuthorized ErrorCodeT = 3 199 200 // ErrorCodeBatchLimitExceeded is return when the number of plugin commands 201 // that are allowed to be executed in a batch request is exceeded. 202 ErrorCodeBatchLimitExceeded ErrorCodeT = 4 203 ) 204 205 var ( 206 // ErrorCodes contains the human readable errors. 207 ErrorCodes = map[ErrorCodeT]string{ 208 ErrorCodeInvalid: "invalid error", 209 ErrorCodeInvalidInput: "invalid input", 210 ErrorCodePluginNotFound: "plugin not found", 211 ErrorCodePluginNotAuthorized: "plugin not authorized", 212 ErrorCodeBatchLimitExceeded: "batch limit exceeded", 213 } 214 ) 215 216 // InternalError is returned in the response body when the server encounters an 217 // unrecoverable error. The ErrorCode field will contain a Unix timestamp that 218 // the user can provide to the server operator to track down the error details 219 // in the logs. The HTTP status code will be 500. 220 type InternalError struct { 221 ErrorCode int64 `json:"errorcode"` 222 } 223 224 // Error satisfies the error interface. 225 func (e InternalError) Error() string { 226 return fmt.Sprintf("internal server error: %v", e.ErrorCode) 227 }