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  }