github.com/decred/politeia@v1.4.0/politeiawww/legacy/records/records.go (about)

     1  // Copyright (c) 2020-2021 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 records
     6  
     7  import (
     8  	"encoding/json"
     9  	"net/http"
    10  
    11  	pdclient "github.com/decred/politeia/politeiad/client"
    12  	v1 "github.com/decred/politeia/politeiawww/api/records/v1"
    13  	"github.com/decred/politeia/politeiawww/config"
    14  	"github.com/decred/politeia/politeiawww/legacy/events"
    15  	"github.com/decred/politeia/politeiawww/legacy/sessions"
    16  	"github.com/decred/politeia/politeiawww/legacy/user"
    17  	"github.com/decred/politeia/util"
    18  )
    19  
    20  // Records is the context for the records API.
    21  type Records struct {
    22  	cfg       *config.Config
    23  	politeiad *pdclient.Client
    24  	userdb    user.Database
    25  	sessions  *sessions.Sessions
    26  	events    *events.Manager
    27  	policy    *v1.PolicyReply
    28  }
    29  
    30  // HandlePolicy is the request handler for the records v1 Policy route.
    31  func (c *Records) HandlePolicy(w http.ResponseWriter, r *http.Request) {
    32  	log.Tracef("HandlePolicy")
    33  
    34  	util.RespondWithJSON(w, http.StatusOK, c.policy)
    35  }
    36  
    37  // HandleNew is the request handler for the records v1 New route.
    38  func (c *Records) HandleNew(w http.ResponseWriter, r *http.Request) {
    39  	log.Tracef("HandleNew")
    40  
    41  	var n v1.New
    42  	decoder := json.NewDecoder(r.Body)
    43  	if err := decoder.Decode(&n); err != nil {
    44  		respondWithError(w, r, "HandleNew: unmarshal",
    45  			v1.UserErrorReply{
    46  				ErrorCode: v1.ErrorCodeInputInvalid,
    47  			})
    48  		return
    49  	}
    50  
    51  	u, err := c.sessions.GetSessionUser(w, r)
    52  	if err != nil {
    53  		respondWithError(w, r,
    54  			"HandleNew: GetSessionUser: %v", err)
    55  		return
    56  	}
    57  
    58  	nr, err := c.processNew(r.Context(), n, *u)
    59  	if err != nil {
    60  		respondWithError(w, r,
    61  			"HandleNew: processNew: %v", err)
    62  		return
    63  	}
    64  
    65  	util.RespondWithJSON(w, http.StatusOK, nr)
    66  }
    67  
    68  // HandleEdit is the request handler for the records v1 Edit route.
    69  func (c *Records) HandleEdit(w http.ResponseWriter, r *http.Request) {
    70  	log.Tracef("HandleEdit")
    71  
    72  	var e v1.Edit
    73  	decoder := json.NewDecoder(r.Body)
    74  	if err := decoder.Decode(&e); err != nil {
    75  		respondWithError(w, r, "HandleEdit: unmarshal",
    76  			v1.UserErrorReply{
    77  				ErrorCode: v1.ErrorCodeInputInvalid,
    78  			})
    79  		return
    80  	}
    81  
    82  	u, err := c.sessions.GetSessionUser(w, r)
    83  	if err != nil {
    84  		respondWithError(w, r,
    85  			"HandleEdit: GetSessionUser: %v", err)
    86  		return
    87  	}
    88  
    89  	er, err := c.processEdit(r.Context(), e, *u)
    90  	if err != nil {
    91  		respondWithError(w, r,
    92  			"HandleEdit: processEdit: %v", err)
    93  		return
    94  	}
    95  
    96  	util.RespondWithJSON(w, http.StatusOK, er)
    97  }
    98  
    99  // HandleSetStatus is the request handler for the records v1 SetStatus route.
   100  func (c *Records) HandleSetStatus(w http.ResponseWriter, r *http.Request) {
   101  	log.Tracef("HandleSetStatus")
   102  
   103  	var ss v1.SetStatus
   104  	decoder := json.NewDecoder(r.Body)
   105  	if err := decoder.Decode(&ss); err != nil {
   106  		respondWithError(w, r, "HandleSetStatus: unmarshal",
   107  			v1.UserErrorReply{
   108  				ErrorCode: v1.ErrorCodeInputInvalid,
   109  			})
   110  		return
   111  	}
   112  
   113  	u, err := c.sessions.GetSessionUser(w, r)
   114  	if err != nil {
   115  		respondWithError(w, r,
   116  			"HandleSetStatus: GetSessionUser: %v", err)
   117  		return
   118  	}
   119  
   120  	ssr, err := c.processSetStatus(r.Context(), ss, *u)
   121  	if err != nil {
   122  		respondWithError(w, r,
   123  			"HandleSetStatus: processSetStatus: %v", err)
   124  		return
   125  	}
   126  
   127  	util.RespondWithJSON(w, http.StatusOK, ssr)
   128  }
   129  
   130  // HandleDetails is the request handler for the records v1 Details route.
   131  func (c *Records) HandleDetails(w http.ResponseWriter, r *http.Request) {
   132  	log.Tracef("HandleDetails")
   133  
   134  	var d v1.Details
   135  	decoder := json.NewDecoder(r.Body)
   136  	if err := decoder.Decode(&d); err != nil {
   137  		respondWithError(w, r, "HandleDetails: unmarshal",
   138  			v1.UserErrorReply{
   139  				ErrorCode: v1.ErrorCodeInputInvalid,
   140  			})
   141  		return
   142  	}
   143  
   144  	// Lookup session user. This is a public route so a session may not
   145  	// exist. Ignore any session not found errors.
   146  	u, err := c.sessions.GetSessionUser(w, r)
   147  	if err != nil && err != sessions.ErrSessionNotFound {
   148  		respondWithError(w, r,
   149  			"HandleDetails: GetSessionUser: %v", err)
   150  		return
   151  	}
   152  
   153  	dr, err := c.processDetails(r.Context(), d, u)
   154  	if err != nil {
   155  		respondWithError(w, r,
   156  			"HandleDetails: processDetails: %v", err)
   157  		return
   158  	}
   159  
   160  	util.RespondWithJSON(w, http.StatusOK, dr)
   161  }
   162  
   163  // HandleTimestamps is the request handler for the records v1 Timestamps route.
   164  func (c *Records) HandleTimestamps(w http.ResponseWriter, r *http.Request) {
   165  	log.Tracef("HandleTimestamps")
   166  
   167  	var t v1.Timestamps
   168  	decoder := json.NewDecoder(r.Body)
   169  	if err := decoder.Decode(&t); err != nil {
   170  		respondWithError(w, r, "HandleTimestamps: unmarshal",
   171  			v1.UserErrorReply{
   172  				ErrorCode: v1.ErrorCodeInputInvalid,
   173  			})
   174  		return
   175  	}
   176  
   177  	// Lookup session user. This is a public route so a session may not
   178  	// exist. Ignore any session not found errors.
   179  	u, err := c.sessions.GetSessionUser(w, r)
   180  	if err != nil && err != sessions.ErrSessionNotFound {
   181  		respondWithError(w, r,
   182  			"HandleTimestamps: getSessionUser: %v", err)
   183  		return
   184  	}
   185  
   186  	isAdmin := u != nil && u.Admin
   187  	tr, err := c.processTimestamps(r.Context(), t, isAdmin)
   188  	if err != nil {
   189  		respondWithError(w, r,
   190  			"HandleTimestamps: processTimestamps: %v", err)
   191  		return
   192  	}
   193  
   194  	util.RespondWithJSON(w, http.StatusOK, tr)
   195  }
   196  
   197  // HandleRecords is the request handler for the records v1 Records route.
   198  func (c *Records) HandleRecords(w http.ResponseWriter, r *http.Request) {
   199  	log.Tracef("HandleRecords")
   200  
   201  	var rs v1.Records
   202  	decoder := json.NewDecoder(r.Body)
   203  	if err := decoder.Decode(&rs); err != nil {
   204  		respondWithError(w, r, "HandleRecords: unmarshal",
   205  			v1.UserErrorReply{
   206  				ErrorCode: v1.ErrorCodeInputInvalid,
   207  			})
   208  		return
   209  	}
   210  
   211  	// Lookup session user. This is a public route so a session may not
   212  	// exist. Ignore any session not found errors.
   213  	u, err := c.sessions.GetSessionUser(w, r)
   214  	if err != nil && err != sessions.ErrSessionNotFound {
   215  		respondWithError(w, r,
   216  			"HandleRecords: GetSessionUser: %v", err)
   217  		return
   218  	}
   219  
   220  	rsr, err := c.processRecords(r.Context(), rs, u)
   221  	if err != nil {
   222  		respondWithError(w, r,
   223  			"HandleRecords: processRecords: %v", err)
   224  		return
   225  	}
   226  
   227  	util.RespondWithJSON(w, http.StatusOK, rsr)
   228  }
   229  
   230  // HandleInventory is the request handler for the records v1 Inventory route.
   231  func (c *Records) HandleInventory(w http.ResponseWriter, r *http.Request) {
   232  	log.Tracef("HandleInventory")
   233  
   234  	var i v1.Inventory
   235  	decoder := json.NewDecoder(r.Body)
   236  	if err := decoder.Decode(&i); err != nil {
   237  		respondWithError(w, r, "HandleInventory: unmarshal",
   238  			v1.UserErrorReply{
   239  				ErrorCode: v1.ErrorCodeInputInvalid,
   240  			})
   241  		return
   242  	}
   243  
   244  	// Lookup session user. This is a public route so a session may not
   245  	// exist. Ignore any session not found errors.
   246  	u, err := c.sessions.GetSessionUser(w, r)
   247  	if err != nil && err != sessions.ErrSessionNotFound {
   248  		respondWithError(w, r,
   249  			"HandleInventory: GetSessionUser: %v", err)
   250  		return
   251  	}
   252  
   253  	ir, err := c.processInventory(r.Context(), i, u)
   254  	if err != nil {
   255  		respondWithError(w, r,
   256  			"HandleInventory: processInventory: %v", err)
   257  		return
   258  	}
   259  
   260  	util.RespondWithJSON(w, http.StatusOK, ir)
   261  }
   262  
   263  // HandleInventoryOrdered is the request handler for the records v1
   264  // InventoryOrdered route.
   265  func (c *Records) HandleInventoryOrdered(w http.ResponseWriter, r *http.Request) {
   266  	log.Tracef("HandleInventoryOrdered")
   267  
   268  	var i v1.InventoryOrdered
   269  	decoder := json.NewDecoder(r.Body)
   270  	if err := decoder.Decode(&i); err != nil {
   271  		respondWithError(w, r, "HandleInventoryOrdered: unmarshal",
   272  			v1.UserErrorReply{
   273  				ErrorCode: v1.ErrorCodeInputInvalid,
   274  			})
   275  		return
   276  	}
   277  
   278  	// Lookup session user. This is a public route so a session may not
   279  	// exist. Ignore any session not found errors.
   280  	u, err := c.sessions.GetSessionUser(w, r)
   281  	if err != nil && err != sessions.ErrSessionNotFound {
   282  		respondWithError(w, r,
   283  			"HandleInventoryOrdered: GetSessionUser: %v", err)
   284  		return
   285  	}
   286  
   287  	ir, err := c.processInventoryOrdered(r.Context(), i, u)
   288  	if err != nil {
   289  		respondWithError(w, r,
   290  			"HandleInventoryOrdered: processInventoryOrdered: %v", err)
   291  		return
   292  	}
   293  
   294  	util.RespondWithJSON(w, http.StatusOK, ir)
   295  }
   296  
   297  // HandleUserRecords is the request handler for the records v1 UserRecords
   298  // route.
   299  func (c *Records) HandleUserRecords(w http.ResponseWriter, r *http.Request) {
   300  	log.Tracef("HandleUserRecords")
   301  
   302  	var ur v1.UserRecords
   303  	decoder := json.NewDecoder(r.Body)
   304  	if err := decoder.Decode(&ur); err != nil {
   305  		respondWithError(w, r, "HandleUserRecords: unmaurhal",
   306  			v1.UserErrorReply{
   307  				ErrorCode: v1.ErrorCodeInputInvalid,
   308  			})
   309  		return
   310  	}
   311  
   312  	// Lookup session user. This is a public route so a session may not
   313  	// exist. Ignore any session not found errour.
   314  	u, err := c.sessions.GetSessionUser(w, r)
   315  	if err != nil && err != sessions.ErrSessionNotFound {
   316  		respondWithError(w, r,
   317  			"HandleUserRecords: GetSessionUser: %v", err)
   318  		return
   319  	}
   320  
   321  	urr, err := c.processUserRecords(r.Context(), ur, u)
   322  	if err != nil {
   323  		respondWithError(w, r,
   324  			"HandleUserRecords: processsUserRecords: %v", err)
   325  		return
   326  	}
   327  
   328  	util.RespondWithJSON(w, http.StatusOK, urr)
   329  }
   330  
   331  // New returns a new Records context.
   332  func New(cfg *config.Config, pdc *pdclient.Client, udb user.Database, s *sessions.Sessions, e *events.Manager) *Records {
   333  	return &Records{
   334  		cfg:       cfg,
   335  		politeiad: pdc,
   336  		userdb:    udb,
   337  		sessions:  s,
   338  		events:    e,
   339  		policy: &v1.PolicyReply{
   340  			RecordsPageSize:   v1.RecordsPageSize,
   341  			InventoryPageSize: v1.InventoryPageSize,
   342  		},
   343  	}
   344  }