github.com/decred/politeia@v1.4.0/politeiawww/api/www/v1/v1.go (about) 1 // Copyright (c) 2017-2020 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 v1 6 7 import ( 8 "fmt" 9 10 "github.com/decred/politeia/politeiad/backend/gitbe/decredplugin" 11 ) 12 13 type ErrorStatusT int 14 type PropStateT int 15 type PropStatusT int 16 type PropVoteStatusT int 17 type UserManageActionT int 18 type EmailNotificationT int 19 type VoteT int 20 type TOTPMethodT int 21 22 const ( 23 PoliteiaWWWAPIVersion = 1 // API version this backend understands 24 25 CsrfToken = "X-CSRF-Token" // CSRF token for replies 26 Forward = "X-Forwarded-For" // Proxy header 27 28 RouteVersion = "/version" 29 RoutePolicy = "/policy" 30 RouteSecret = "/secret" 31 RouteLogin = "/login" 32 RouteLogout = "/logout" 33 RouteUserMe = "/user/me" 34 RouteNewUser = "/user/new" 35 RouteResendVerification = "/user/new/resend" 36 RouteVerifyNewUser = "/user/verify" 37 RouteEditUser = "/user/edit" 38 RouteUpdateUserKey = "/user/key" 39 RouteVerifyUpdateUserKey = "/user/key/verify" 40 RouteChangeUsername = "/user/username/change" 41 RouteChangePassword = "/user/password/change" 42 RouteResetPassword = "/user/password/reset" 43 RouteVerifyResetPassword = "/user/password/reset/verify" 44 RouteUserRegistrationPayment = "/user/payments/registration" 45 RouteUserProposalPaywall = "/user/payments/paywall" 46 RouteUserProposalPaywallTx = "/user/payments/paywalltx" 47 RouteUserProposalCredits = "/user/payments/credits" 48 RouteUserPaymentsRescan = "/user/payments/rescan" 49 RouteManageUser = "/user/manage" 50 RouteSetTOTP = "/user/totp" 51 RouteVerifyTOTP = "/user/verifytotp" 52 RouteUserDetails = "/user/{userid:[0-9a-zA-Z-]{36}}" 53 RouteUsers = "/users" 54 RouteUnauthenticatedWebSocket = "/ws" 55 RouteAuthenticatedWebSocket = "/aws" 56 57 // The following routes have been DEPRECATED. 58 RouteTokenInventory = "/proposals/tokeninventory" 59 RouteProposalDetails = "/proposals/{token:[A-Fa-f0-9]{7,64}}" 60 RouteAllVetted = "/proposals/vetted" 61 RouteBatchProposals = "/proposals/batch" 62 RouteVoteStatus = "/proposals/{token:[A-Fa-f0-9]{7,64}}/votestatus" 63 RouteAllVoteStatus = "/proposals/votestatus" 64 RouteBatchVoteSummary = "/proposals/batchvotesummary" 65 RouteActiveVote = "/proposals/activevote" 66 RouteCastVotes = "/proposals/castvotes" 67 RouteVoteResults = "/proposals/{token:[A-Fa-f0-9]{7,64}}/votes" 68 69 // The following routes are NO LONGER SUPPORTED. 70 RouteNewProposal = "/proposals/new" 71 RouteEditProposal = "/proposals/edit" 72 RouteAuthorizeVote = "/proposals/authorizevote" 73 RouteStartVote = "/proposals/startvote" 74 RouteSetProposalStatus = "/proposals/{token:[A-Fa-f0-9]{7,64}}/status" 75 RouteCommentsGet = "/proposals/{token:[A-Fa-f0-9]{7,64}}/comments" 76 RouteNewComment = "/comments/new" 77 RouteLikeComment = "/comments/like" 78 RouteCensorComment = "/comments/censor" 79 RouteUserCommentsLikes = "/user/proposals/{token:[A-z0-9]{64}}/commentslikes" 80 RouteUserProposals = "/user/proposals" 81 82 // VerificationTokenSize is the size of verification token in bytes 83 VerificationTokenSize = 32 84 85 // TokenPrefixLength is the length of the token prefix that can 86 // be used in RouteProposalDetails. This should match what is defined 87 // in politeiad, and once a Policy route is created in politeiad, 88 // this should be removed. 89 TokenPrefixLength = 7 90 91 // VerificationExpiryHours is the number of hours before the 92 // verification token expires 93 VerificationExpiryHours = 24 94 95 // PolicyIdexFilename is the file name of the proposal markdown 96 // file. Every proposal is required to have a index file. The index 97 // file should contain the proposal content. 98 PolicyIndexFilename = "index.md" 99 100 // PolicyMaxImages is the maximum number of images accepted 101 // when creating a new proposal 102 PolicyMaxImages = 5 103 104 // PolicyMaxImageSize is the maximum image file size (in bytes) 105 // accepted when creating a new proposal 106 PolicyMaxImageSize = 512 * 1024 107 108 // PolicyMaxMDs is the maximum number of markdown files accepted 109 // when creating a new proposal. 110 PolicyMaxMDs = 1 111 112 // PolicyMaxMDSize is the maximum markdown file size (in bytes) 113 // accepted when creating a new proposal 114 PolicyMaxMDSize = 512 * 1024 115 116 // PolicyMinPasswordLength is the minimum number of characters 117 // accepted for user passwords 118 PolicyMinPasswordLength = 8 119 120 // PolicyMaxUsernameLength is the max length of a username 121 PolicyMaxUsernameLength = 30 122 123 // PolicyMinUsernameLength is the min length of a username 124 PolicyMinUsernameLength = 3 125 126 // PolicyMaxProposalNameLength is the max length of a proposal name 127 PolicyMaxProposalNameLength = 80 128 129 // PolicyMinProposalNameLength is the min length of a proposal name 130 PolicyMinProposalNameLength = 8 131 132 // PolicyMaxCommentLength is the maximum number of characters 133 // accepted for comments 134 PolicyMaxCommentLength = 8000 135 136 // ProposalListPageSize is the maximum number of proposals returned 137 // for the routes that return lists of proposals 138 ProposalListPageSize = 20 139 140 // UserListPageSize is the maximum number of users returned 141 // for the routes that return lists of users 142 UserListPageSize = 20 143 144 // Error status codes 145 ErrorStatusInvalid ErrorStatusT = 0 146 ErrorStatusInvalidPassword ErrorStatusT = 1 147 ErrorStatusMalformedEmail ErrorStatusT = 2 148 ErrorStatusVerificationTokenInvalid ErrorStatusT = 3 149 ErrorStatusVerificationTokenExpired ErrorStatusT = 4 150 ErrorStatusProposalMissingFiles ErrorStatusT = 5 151 ErrorStatusProposalNotFound ErrorStatusT = 6 152 ErrorStatusProposalDuplicateFilenames ErrorStatusT = 7 153 ErrorStatusProposalInvalidTitle ErrorStatusT = 8 154 ErrorStatusMaxMDsExceededPolicy ErrorStatusT = 9 155 ErrorStatusMaxImagesExceededPolicy ErrorStatusT = 10 156 ErrorStatusMaxMDSizeExceededPolicy ErrorStatusT = 11 157 ErrorStatusMaxImageSizeExceededPolicy ErrorStatusT = 12 158 ErrorStatusMalformedPassword ErrorStatusT = 13 159 ErrorStatusCommentNotFound ErrorStatusT = 14 160 ErrorStatusInvalidFilename ErrorStatusT = 15 161 ErrorStatusInvalidFileDigest ErrorStatusT = 16 162 ErrorStatusInvalidBase64 ErrorStatusT = 17 163 ErrorStatusInvalidMIMEType ErrorStatusT = 18 164 ErrorStatusUnsupportedMIMEType ErrorStatusT = 19 165 ErrorStatusInvalidPropStatusTransition ErrorStatusT = 20 166 ErrorStatusInvalidPublicKey ErrorStatusT = 21 167 ErrorStatusNoPublicKey ErrorStatusT = 22 168 ErrorStatusInvalidSignature ErrorStatusT = 23 169 ErrorStatusInvalidInput ErrorStatusT = 24 170 ErrorStatusInvalidSigningKey ErrorStatusT = 25 171 ErrorStatusCommentLengthExceededPolicy ErrorStatusT = 26 172 ErrorStatusUserNotFound ErrorStatusT = 27 173 ErrorStatusWrongStatus ErrorStatusT = 28 174 ErrorStatusNotLoggedIn ErrorStatusT = 29 175 ErrorStatusUserNotPaid ErrorStatusT = 30 176 ErrorStatusReviewerAdminEqualsAuthor ErrorStatusT = 31 177 ErrorStatusMalformedUsername ErrorStatusT = 32 178 ErrorStatusDuplicateUsername ErrorStatusT = 33 179 ErrorStatusVerificationTokenUnexpired ErrorStatusT = 34 180 ErrorStatusCannotVerifyPayment ErrorStatusT = 35 181 ErrorStatusDuplicatePublicKey ErrorStatusT = 36 182 ErrorStatusInvalidPropVoteStatus ErrorStatusT = 37 183 ErrorStatusUserLocked ErrorStatusT = 38 184 ErrorStatusNoProposalCredits ErrorStatusT = 39 185 ErrorStatusInvalidUserManageAction ErrorStatusT = 40 186 ErrorStatusUserActionNotAllowed ErrorStatusT = 41 187 ErrorStatusWrongVoteStatus ErrorStatusT = 42 188 ErrorStatusUnused1 ErrorStatusT = 43 // XXX 189 ErrorStatusCannotVoteOnPropComment ErrorStatusT = 44 190 ErrorStatusChangeMessageCannotBeBlank ErrorStatusT = 45 191 ErrorStatusCensorReasonCannotBeBlank ErrorStatusT = 46 192 ErrorStatusCannotCensorComment ErrorStatusT = 47 193 ErrorStatusUserNotAuthor ErrorStatusT = 48 194 ErrorStatusVoteNotAuthorized ErrorStatusT = 49 195 ErrorStatusVoteAlreadyAuthorized ErrorStatusT = 50 196 ErrorStatusInvalidAuthVoteAction ErrorStatusT = 51 197 ErrorStatusUserDeactivated ErrorStatusT = 52 198 ErrorStatusInvalidPropVoteBits ErrorStatusT = 53 199 ErrorStatusInvalidPropVoteParams ErrorStatusT = 54 200 ErrorStatusEmailNotVerified ErrorStatusT = 55 201 ErrorStatusInvalidUUID ErrorStatusT = 56 202 ErrorStatusInvalidLikeCommentAction ErrorStatusT = 57 203 ErrorStatusInvalidCensorshipToken ErrorStatusT = 58 204 ErrorStatusEmailAlreadyVerified ErrorStatusT = 59 205 ErrorStatusNoProposalChanges ErrorStatusT = 60 206 ErrorStatusMaxProposalsExceededPolicy ErrorStatusT = 61 207 ErrorStatusDuplicateComment ErrorStatusT = 62 208 ErrorStatusInvalidLogin ErrorStatusT = 63 209 ErrorStatusCommentIsCensored ErrorStatusT = 64 210 ErrorStatusInvalidProposalVersion ErrorStatusT = 65 211 ErrorStatusMetadataInvalid ErrorStatusT = 66 212 ErrorStatusMetadataMissing ErrorStatusT = 67 213 ErrorStatusMetadataDigestInvalid ErrorStatusT = 68 214 ErrorStatusInvalidVoteType ErrorStatusT = 69 215 ErrorStatusInvalidVoteOptions ErrorStatusT = 70 216 ErrorStatusLinkByDeadlineNotMet ErrorStatusT = 71 217 ErrorStatusNoLinkedProposals ErrorStatusT = 72 218 ErrorStatusInvalidLinkTo ErrorStatusT = 73 219 ErrorStatusInvalidLinkBy ErrorStatusT = 74 220 ErrorStatusInvalidRunoffVote ErrorStatusT = 75 221 ErrorStatusWrongProposalType ErrorStatusT = 76 222 ErrorStatusTOTPFailedValidation ErrorStatusT = 77 223 ErrorStatusTOTPInvalidType ErrorStatusT = 78 224 ErrorStatusRequiresTOTPCode ErrorStatusT = 79 225 ErrorStatusTOTPWaitForNewCode ErrorStatusT = 80 226 ErrorStatusLast ErrorStatusT = 81 227 228 // Proposal state codes 229 // 230 // PropStateUnvetted includes proposals with a status of: 231 // * PropStatusNotReviewed 232 // * PropStatusUnreviewedChanges 233 // * PropStatusCensored 234 // PropStateVetted includes proposals with a status of: 235 // * PropStatusPublic 236 // * PropStatusAbandoned 237 // 238 // Proposal states correspond to the unvetted and vetted politeiad 239 // repositories. 240 PropStateInvalid PropStateT = 0 // Invalid state 241 PropStateUnvetted PropStateT = 1 // Unvetted proposal 242 PropStateVetted PropStateT = 2 // Vetted proposal 243 244 // Proposal status codes (set and get) 245 PropStatusInvalid PropStatusT = 0 // Invalid status 246 PropStatusNotFound PropStatusT = 1 // Proposal not found 247 PropStatusNotReviewed PropStatusT = 2 // Proposal has not been reviewed 248 PropStatusCensored PropStatusT = 3 // Proposal has been censored 249 PropStatusPublic PropStatusT = 4 // Proposal is publicly visible 250 PropStatusUnreviewedChanges PropStatusT = 5 // Proposal is not public and has unreviewed changes 251 PropStatusAbandoned PropStatusT = 6 // Proposal has been declared abandoned by an admin 252 PropStatusLast PropStatusT = 7 // Unit test only 253 254 // Proposal vote status codes 255 PropVoteStatusInvalid PropVoteStatusT = 0 // Invalid vote status 256 PropVoteStatusNotAuthorized PropVoteStatusT = 1 // Vote has not been authorized by author 257 PropVoteStatusAuthorized PropVoteStatusT = 2 // Vote has been authorized by author 258 PropVoteStatusStarted PropVoteStatusT = 3 // Proposal vote has been started 259 PropVoteStatusFinished PropVoteStatusT = 4 // Proposal vote has been finished 260 PropVoteStatusDoesntExist PropVoteStatusT = 5 // Proposal doesn't exist 261 PropVoteLast PropVoteStatusT = 6 // Unit test only 262 263 // Vote types 264 // 265 // VoteTypeStandard is used to indicate a simple approve or reject 266 // proposal vote where the winner is the voting option that has met 267 // the specified pass and quorum requirements. 268 // 269 // VoteTypeRunoff specifies a runoff vote that multiple proposals compete in. 270 // All proposals are voted on like normal, but there can only be one winner 271 // in a runoff vote. The winner is the proposal that meets the quorum 272 // requirement, meets the pass requirement, and that has the most net yes 273 // votes. The winning proposal is considered approved and all other proposals 274 // are considered rejected. If no proposals meet the quorum and pass 275 // requirements then all proposals are considered rejected. 276 // Note: in a runoff vote it is possible for a proposal to meet the quorum 277 // and pass requirements but still be rejected if it does not have the most 278 // net yes votes. 279 VoteTypeInvalid VoteT = 0 280 VoteTypeStandard VoteT = 1 281 VoteTypeRunoff VoteT = 2 282 283 // User manage actions 284 UserManageInvalid UserManageActionT = 0 // Invalid action type 285 UserManageExpireNewUserVerification UserManageActionT = 1 286 UserManageExpireUpdateKeyVerification UserManageActionT = 2 287 UserManageExpireResetPasswordVerification UserManageActionT = 3 288 UserManageClearUserPaywall UserManageActionT = 4 289 UserManageUnlock UserManageActionT = 5 290 UserManageDeactivate UserManageActionT = 6 291 UserManageReactivate UserManageActionT = 7 292 UserManageLast UserManageActionT = 8 293 294 // Email notification types 295 NotificationEmailMyProposalStatusChange EmailNotificationT = 1 << 0 296 NotificationEmailMyProposalVoteStarted EmailNotificationT = 1 << 1 297 NotificationEmailRegularProposalVetted EmailNotificationT = 1 << 2 298 NotificationEmailRegularProposalEdited EmailNotificationT = 1 << 3 299 NotificationEmailRegularProposalVoteStarted EmailNotificationT = 1 << 4 300 NotificationEmailAdminProposalNew EmailNotificationT = 1 << 5 301 NotificationEmailAdminProposalVoteAuthorized EmailNotificationT = 1 << 6 302 NotificationEmailCommentOnMyProposal EmailNotificationT = 1 << 7 303 NotificationEmailCommentOnMyComment EmailNotificationT = 1 << 8 304 305 // Time-base one time password types 306 TOTPTypeInvalid TOTPMethodT = 0 // Invalid TOTP type 307 TOTPTypeBasic TOTPMethodT = 1 308 ) 309 310 var ( 311 // PolicyProposalNameSupportedChars is the regular expression of a valid 312 // proposal name 313 PolicyProposalNameSupportedChars = []string{ 314 "A-z", "0-9", "&", ".", ",", ":", ";", "-", " ", "@", "+", "#", "/", 315 "(", ")", "!", "?", "\"", "'"} 316 317 // PolicyUsernameSupportedChars is the regular expression of a valid 318 // username 319 PolicyUsernameSupportedChars = []string{ 320 "a-z", "0-9", ".", ",", ":", ";", "-", "@", "+", "(", ")", "_"} 321 322 // PoliteiaWWWAPIRoute is the prefix to the API route 323 PoliteiaWWWAPIRoute = fmt.Sprintf("/v%v", PoliteiaWWWAPIVersion) 324 325 // CookieSession is the cookie name that indicates that a user is 326 // logged in. 327 CookieSession = "session" 328 329 // ErrorStatus converts error status codes to human readable text. 330 ErrorStatus = map[ErrorStatusT]string{ 331 ErrorStatusInvalid: "invalid error status", 332 ErrorStatusInvalidPassword: "invalid password", 333 ErrorStatusMalformedEmail: "malformed email", 334 ErrorStatusVerificationTokenInvalid: "invalid verification token", 335 ErrorStatusVerificationTokenExpired: "expired verification token", 336 ErrorStatusProposalMissingFiles: "missing proposal files", 337 ErrorStatusProposalNotFound: "proposal not found", 338 ErrorStatusProposalDuplicateFilenames: "duplicate proposal files", 339 ErrorStatusProposalInvalidTitle: "invalid proposal title", 340 ErrorStatusMaxMDsExceededPolicy: "maximum markdown files exceeded", 341 ErrorStatusMaxImagesExceededPolicy: "maximum image files exceeded", 342 ErrorStatusMaxMDSizeExceededPolicy: "maximum markdown file size exceeded", 343 ErrorStatusMaxImageSizeExceededPolicy: "maximum image file size exceeded", 344 ErrorStatusMalformedPassword: "malformed password", 345 ErrorStatusCommentNotFound: "comment not found", 346 ErrorStatusInvalidFilename: "invalid filename", 347 ErrorStatusInvalidFileDigest: "invalid file digest", 348 ErrorStatusInvalidBase64: "invalid base64 file content", 349 ErrorStatusInvalidMIMEType: "invalid MIME type detected for file", 350 ErrorStatusUnsupportedMIMEType: "unsupported MIME type for file", 351 ErrorStatusInvalidPropStatusTransition: "invalid proposal status", 352 ErrorStatusInvalidPublicKey: "invalid public key", 353 ErrorStatusNoPublicKey: "no active public key", 354 ErrorStatusInvalidSignature: "invalid signature", 355 ErrorStatusInvalidInput: "invalid input", 356 ErrorStatusInvalidSigningKey: "invalid signing key", 357 ErrorStatusCommentLengthExceededPolicy: "maximum comment length exceeded", 358 ErrorStatusUserNotFound: "user not found", 359 ErrorStatusWrongStatus: "wrong proposal status", 360 ErrorStatusNotLoggedIn: "user not logged in", 361 ErrorStatusUserNotPaid: "user hasn't paid paywall", 362 ErrorStatusReviewerAdminEqualsAuthor: "user cannot change the status of his own proposal", 363 ErrorStatusMalformedUsername: "malformed username", 364 ErrorStatusDuplicateUsername: "duplicate username", 365 ErrorStatusVerificationTokenUnexpired: "verification token not yet expired", 366 ErrorStatusCannotVerifyPayment: "cannot verify payment at this time", 367 ErrorStatusDuplicatePublicKey: "public key already taken by another user", 368 ErrorStatusInvalidPropVoteStatus: "invalid proposal vote status", 369 ErrorStatusUserLocked: "user locked due to too many login attempts", 370 ErrorStatusNoProposalCredits: "no proposal credits", 371 ErrorStatusInvalidUserManageAction: "invalid user edit action", 372 ErrorStatusUserActionNotAllowed: "user action is not allowed", 373 ErrorStatusWrongVoteStatus: "wrong proposal vote status", 374 ErrorStatusUnused1: "UNUSED STATUS 1", 375 ErrorStatusCannotVoteOnPropComment: "cannot vote on proposal comment", 376 ErrorStatusChangeMessageCannotBeBlank: "status change message cannot be blank", 377 ErrorStatusCensorReasonCannotBeBlank: "censor comment reason cannot be blank", 378 ErrorStatusCannotCensorComment: "cannot censor comment", 379 ErrorStatusUserNotAuthor: "user is not the proposal author", 380 ErrorStatusVoteNotAuthorized: "vote has not been authorized", 381 ErrorStatusVoteAlreadyAuthorized: "vote has already been authorized", 382 ErrorStatusInvalidAuthVoteAction: "invalid authorize vote action", 383 ErrorStatusUserDeactivated: "user account is deactivated", 384 ErrorStatusInvalidPropVoteBits: "invalid proposal vote option bits", 385 ErrorStatusInvalidPropVoteParams: "invalid proposal vote parameters", 386 ErrorStatusEmailNotVerified: "email address is not verified", 387 ErrorStatusInvalidUUID: "invalid user UUID", 388 ErrorStatusInvalidLikeCommentAction: "invalid like comment action", 389 ErrorStatusInvalidCensorshipToken: "invalid proposal censorship token", 390 ErrorStatusEmailAlreadyVerified: "email address is already verified", 391 ErrorStatusNoProposalChanges: "no changes found in proposal", 392 ErrorStatusMaxProposalsExceededPolicy: "max proposals exceeded", 393 ErrorStatusDuplicateComment: "duplicate comment", 394 ErrorStatusInvalidLogin: "invalid login credentials", 395 ErrorStatusCommentIsCensored: "comment is censored", 396 ErrorStatusInvalidProposalVersion: "invalid proposal version", 397 ErrorStatusMetadataInvalid: "invalid metadata", 398 ErrorStatusMetadataMissing: "missing metadata", 399 ErrorStatusMetadataDigestInvalid: "metadata digest invalid", 400 ErrorStatusInvalidVoteType: "invalid vote type", 401 ErrorStatusInvalidVoteOptions: "invalid vote options", 402 ErrorStatusLinkByDeadlineNotMet: "linkby deadline note met yet", 403 ErrorStatusNoLinkedProposals: "no linked proposals", 404 ErrorStatusInvalidLinkTo: "invalid proposal linkto", 405 ErrorStatusInvalidLinkBy: "invalid proposal linkby", 406 ErrorStatusInvalidRunoffVote: "invalid runoff vote", 407 ErrorStatusWrongProposalType: "wrong proposal type", 408 ErrorStatusTOTPFailedValidation: "the provided passcode does not match the saved secret key", 409 ErrorStatusTOTPInvalidType: "invalid totp type", 410 ErrorStatusRequiresTOTPCode: "login requires totp code", 411 ErrorStatusTOTPWaitForNewCode: "must wait until next totp code window", 412 } 413 414 // PropStatus converts propsal status codes to human readable text 415 PropStatus = map[PropStatusT]string{ 416 PropStatusInvalid: "invalid proposal status", 417 PropStatusNotFound: "not found", 418 PropStatusNotReviewed: "unreviewed", 419 PropStatusCensored: "censored", 420 PropStatusPublic: "public", 421 PropStatusUnreviewedChanges: "unreviewed changes", 422 PropStatusAbandoned: "abandoned", 423 } 424 425 // PropVoteStatus converts votes status codes to human readable text 426 PropVoteStatus = map[PropVoteStatusT]string{ 427 PropVoteStatusInvalid: "invalid vote status", 428 PropVoteStatusNotAuthorized: "voting has not been authorized by author", 429 PropVoteStatusAuthorized: "voting has been authorized by author", 430 PropVoteStatusStarted: "voting active", 431 PropVoteStatusFinished: "voting finished", 432 PropVoteStatusDoesntExist: "proposal does not exist", 433 } 434 435 // UserManageAction converts user edit actions to human readable text 436 UserManageAction = map[UserManageActionT]string{ 437 UserManageInvalid: "invalid action", 438 UserManageExpireNewUserVerification: "expire new user verification", 439 UserManageExpireUpdateKeyVerification: "expire update key verification", 440 UserManageExpireResetPasswordVerification: "expire reset password verification", 441 UserManageClearUserPaywall: "clear user paywall", 442 UserManageUnlock: "unlock user", 443 UserManageDeactivate: "deactivate user", 444 UserManageReactivate: "reactivate user", 445 } 446 ) 447 448 // File describes an individual file that is part of the proposal. The 449 // directory structure must be flattened. The server side SHALL verify MIME 450 // and Digest. 451 type File struct { 452 // Meta-data 453 Name string `json:"name"` // Suggested filename 454 MIME string `json:"mime"` // Mime type 455 Digest string `json:"digest"` // Digest of unencoded payload 456 457 // Data 458 Payload string `json:"payload"` // File content, base64 encoded 459 } 460 461 const ( 462 // Metadata hints 463 HintProposalMetadata = "proposalmetadata" 464 ) 465 466 // ProposalMetadata contains metadata that is specified by the user on proposal 467 // submission. It is attached to a proposal submission as a Metadata object. 468 // 469 // LinkBy must allow for a minimum of one week after the proposal vote ends for 470 // RFP submissions to be submitted. The LinkBy field is validated on both 471 // proposal submission and before the proposal vote is started to ensure that 472 // the RFP submissions have sufficient time to be submitted. 473 type ProposalMetadata struct { 474 Name string `json:"name"` // Proposal name 475 LinkTo string `json:"linkto,omitempty"` // Token of proposal to link to 476 LinkBy int64 `json:"linkby,omitempty"` // UNIX timestamp of RFP deadline 477 } 478 479 // Metadata describes user specified metadata. 480 // 481 // Payload is the base64 encoding of the JSON encoded metadata. Its required 482 // to be base64 encoded because it's stored in politeiad as a file and the 483 // politeiad file payload must be base64. 484 type Metadata struct { 485 Digest string `json:"digest"` // SHA256 digest of JSON encoded payload 486 Hint string `json:"hint"` // Hint that describes the payload 487 Payload string `json:"payload"` // Base64 encoded metadata content 488 } 489 490 // CensorshipRecord contains the proof that a proposal was accepted for review. 491 // The proof is verifiable on the client side. 492 // 493 // The Merkle field contains the ordered merkle root of all files and metadata 494 // in the proposal. The Token field contains a random censorship token that is 495 // signed by the server private key. The token can be used on the client to 496 // verify the authenticity of the CensorshipRecord. 497 type CensorshipRecord struct { 498 Token string `json:"token"` // Censorship token 499 Merkle string `json:"merkle"` // Merkle root of proposal 500 Signature string `json:"signature"` // Server side signature of []byte(Merkle+Token) 501 } 502 503 // VoteSummary contains a summary of the vote information for a specific 504 // proposal. It is a light weight version of the VoteResultsReply that is used 505 // when the full ticket snapshot or the full cast vote data is not needed. 506 type VoteSummary struct { 507 Status PropVoteStatusT `json:"status"` // Vote status 508 Approved bool `json:"approved"` // Was the vote approved 509 Type VoteT `json:"type,omitempty"` // Vote type 510 EligibleTickets uint32 `json:"eligibletickets,omitempty"` // Number of eligible tickets 511 Duration uint32 `json:"duration,omitempty"` // Duration of vote 512 EndHeight uint64 `json:"endheight,omitempty"` // Vote end height 513 QuorumPercentage uint32 `json:"quorumpercentage,omitempty"` // Percent of eligible votes required for quorum 514 PassPercentage uint32 `json:"passpercentage,omitempty"` // Percent of total votes required to pass 515 Results []VoteOptionResult `json:"results,omitempty"` // Vote results 516 } 517 518 // ProposalRecord is an entire proposal and it's content. 519 // 520 // Signature is a signature of the proposal merkle root where the merkle root 521 // contains all Files and Metadata of the proposal. 522 type ProposalRecord struct { 523 Name string `json:"name"` // Suggested short proposal name 524 State PropStateT `json:"state"` // Current state of proposal 525 Status PropStatusT `json:"status"` // Current status of proposal 526 Timestamp int64 `json:"timestamp"` // Last update of proposal 527 UserId string `json:"userid"` // ID of user who submitted proposal 528 Username string `json:"username"` // Username of user who submitted proposal 529 PublicKey string `json:"publickey"` // Key used for signature. 530 Signature string `json:"signature"` // Signature of merkle root 531 NumComments uint `json:"numcomments"` // Number of comments on the proposal 532 Version string `json:"version"` // Record version 533 StatusChangeMessage string `json:"statuschangemessage,omitempty"` // Message associated to the status change 534 PublishedAt int64 `json:"publishedat,omitempty"` // UNIX timestamp of when proposal was published 535 CensoredAt int64 `json:"censoredat,omitempty"` // UNIX timestamp of when proposal was censored 536 AbandonedAt int64 `json:"abandonedat,omitempty"` // UNIX timestamp of when proposal was abandoned 537 LinkTo string `json:"linkto,omitempty"` // Token of linked parent proposal 538 LinkBy int64 `json:"linkby,omitempty"` // UNIX timestamp of RFP deadline 539 LinkedFrom []string `json:"linkedfrom,omitempty"` // Tokens of public props that have linked to this this prop 540 541 Files []File `json:"files"` 542 Metadata []Metadata `json:"metadata"` 543 CensorshipRecord CensorshipRecord `json:"censorshiprecord"` 544 } 545 546 // ProposalCredit contains the details of a proposal credit that has been 547 // purchased by the user. 548 type ProposalCredit struct { 549 PaywallID uint64 `json:"paywallid"` // paywall that created this credit 550 Price uint64 `json:"price"` // Price credit was purchased at in atoms 551 DatePurchased int64 `json:"datepurchased"` // Unix timestamp of the purchase date 552 TxID string `json:"txid"` // Decred tx that purchased this credit 553 } 554 555 // UserError represents an error that is caused by something that the user 556 // did (malformed input, bad timing, etc). 557 type UserError struct { 558 ErrorCode ErrorStatusT 559 ErrorContext []string 560 } 561 562 // Error satisfies the error interface. 563 func (e UserError) Error() string { 564 return fmt.Sprintf("user error code: %v", e.ErrorCode) 565 } 566 567 // ErrorReply are replies that the server returns when it encounters an 568 // unrecoverable problem while executing a command. The HTTP status code will 569 // be 500 and the ErrorCode field will contain a UNIX timestamp that the user 570 // can provide to the server admin to track down the error details in the logs. 571 type ErrorReply struct { 572 ErrorCode int64 `json:"errorcode,omitempty"` 573 ErrorContext []string `json:"errorcontext,omitempty"` 574 } 575 576 // Error satisfies the error interface. 577 func (e ErrorReply) Error() string { 578 return fmt.Sprintf("server error: %v", e.ErrorCode) 579 } 580 581 // Version command is used to determine the lowest API version that this 582 // backend supports and additionally it provides the route to said API. This 583 // call is required in order to establish CSRF for the session. The client 584 // should verify compatibility with the server version. 585 type Version struct{} 586 587 // VersionReply returns information that indicates the lowest version that 588 // this backend supports and additionally the route to the API and the public 589 // signing key of the server. 590 type VersionReply struct { 591 Version uint `json:"version"` // Lowest supported WWW API version 592 Route string `json:"route"` // Prefix to API calls 593 BuildVersion string `json:"buildversion"` // Build version from hosted pi module 594 PubKey string `json:"pubkey"` // Server public key 595 TestNet bool `json:"testnet"` // Network indicator 596 Mode string `json:"mode"` // current politeiawww mode running (piwww or cmswww) 597 ActiveUserSession bool `json:"activeusersession"` // indicates if there is an active user session 598 } 599 600 // NewUser is used to request that a new user be created within the db. 601 // If successful, the user will require verification before being able to login. 602 type NewUser struct { 603 Email string `json:"email"` 604 Password string `json:"password"` 605 PublicKey string `json:"publickey"` 606 Username string `json:"username"` 607 } 608 609 // NewUserReply is used to reply to the NewUser command with an error 610 // if the command is unsuccessful. 611 type NewUserReply struct { 612 VerificationToken string `json:"verificationtoken"` // Server verification token 613 } 614 615 // VerifyNewUser is used to perform verification for the user created through 616 // the NewUser command using the token provided in NewUserReply. 617 type VerifyNewUser struct { 618 Email string `schema:"email"` // User email address 619 VerificationToken string `schema:"verificationtoken"` // Server provided verification token 620 Signature string `schema:"signature"` // Verification token signature 621 } 622 623 // VerifyNewUserReply 624 type VerifyNewUserReply struct{} 625 626 // ResendVerification is used to resent a new user verification email. 627 type ResendVerification struct { 628 Email string `json:"email"` 629 PublicKey string `json:"publickey"` 630 } 631 632 // ResendVerificationReply is used to reply to the ResendVerification command. 633 type ResendVerificationReply struct { 634 VerificationToken string `json:"verificationtoken"` // Server verification token 635 } 636 637 // UpdateUserKey is used to request a new active key. 638 type UpdateUserKey struct { 639 PublicKey string `json:"publickey"` 640 } 641 642 // UpdateUserKeyReply replies to the UpdateUserKey command. 643 type UpdateUserKeyReply struct { 644 VerificationToken string `json:"verificationtoken"` // Server verification token 645 } 646 647 // VerifyUpdateUserKey is used to request a new active key. 648 type VerifyUpdateUserKey struct { 649 VerificationToken string `json:"verificationtoken"` // Server provided verification token 650 Signature string `json:"signature"` // Verification token signature 651 } 652 653 // VerifyUpdateUserKeyReply replies to the VerifyUpdateUserKey command. 654 type VerifyUpdateUserKeyReply struct{} 655 656 // ChangeUsername is used to perform a username change while the user 657 // is logged in. 658 type ChangeUsername struct { 659 Password string `json:"password"` 660 NewUsername string `json:"newusername"` 661 } 662 663 // ChangeUsernameReply is used to perform a username change while the user 664 // is logged in. 665 type ChangeUsernameReply struct{} 666 667 // ChangePassword is used to perform a password change while the user 668 // is logged in. 669 type ChangePassword struct { 670 CurrentPassword string `json:"currentpassword"` 671 NewPassword string `json:"newpassword"` 672 } 673 674 // ChangePasswordReply is used to perform a password change while the user 675 // is logged in. 676 type ChangePasswordReply struct{} 677 678 // ResetPassword is used to perform a password change when the user is not 679 // logged in. If the username and email address match the user record in the 680 // database then a reset password verification token will be email to the user. 681 type ResetPassword struct { 682 Username string `json:"username"` 683 Email string `json:"email"` 684 } 685 686 // ResetPasswordReply is used to reply to the ResetPassword command. The 687 // verification token will only be present if the email server has been 688 // disabled. 689 type ResetPasswordReply struct { 690 VerificationToken string `json:"verificationtoken"` 691 } 692 693 // VerifyResetPassword is used to verify the verification token sent to a user 694 // in the ResestPassword command and will update the user's password with the 695 // provided NewPassword if everything matches. 696 type VerifyResetPassword struct { 697 Username string `json:"username"` 698 VerificationToken string `json:"verificationtoken"` 699 NewPassword string `json:"newpassword"` 700 } 701 702 // VerifyResetPasswordReply is used to reply to the VerifyResetPassword 703 // command. 704 type VerifyResetPasswordReply struct{} 705 706 // UserProposals is used to request a list of proposals that the 707 // user has submitted. This command optionally takes either a Before 708 // or After parameter, which specify a proposal's censorship token. 709 // If After is specified, the "page" returned starts after the proposal 710 // whose censorship token is provided. If Before is specified, the "page" 711 // returned starts before the proposal whose censorship token is provided. 712 // 713 // This request is NO LONGER SUPPORTED. 714 type UserProposals struct { 715 UserId string `schema:"userid"` 716 Before string `schema:"before"` 717 After string `schema:"after"` 718 } 719 720 // UserProposalsReply replies to the UserProposals command with 721 // a list of proposals that the user has submitted and the total 722 // amount of proposals 723 // 724 // This request is NO LONGER SUPPORTED. 725 type UserProposalsReply struct { 726 Proposals []ProposalRecord `json:"proposals"` // user proposals 727 NumOfProposals int `json:"numofproposals"` // number of proposals submitted by the user 728 } 729 730 // Users is used to request a list of users given a filter. 731 type Users struct { 732 Username string `json:"username"` // String which should match or partially match a username 733 Email string `json:"email"` // String which should match or partially match an email 734 PublicKey string `json:"publickey"` // Active or inactive user pubkey 735 736 } 737 738 // UsersReply is a reply to the Users command, replying with a list of users. 739 type UsersReply struct { 740 TotalUsers uint64 `json:"totalusers,omitempty"` // Total number of all users in the database 741 TotalMatches uint64 `json:"totalmatches"` // Total number of users that match the filters 742 Users []AbridgedUser `json:"users"` // List of users that match the filters 743 } 744 745 // AbridgedUser is a shortened version of User that's used for the admin list. 746 type AbridgedUser struct { 747 ID string `json:"id"` 748 Email string `json:"email,omitempty"` 749 Username string `json:"username"` 750 } 751 752 // Login attempts to login the user. Note that by necessity the password 753 // travels in the clear. 754 type Login struct { 755 Email string `json:"email"` 756 Password string `json:"password"` 757 Code string `json:"code,omitempty"` // TOTP code based on user's TOTP secret (if verified) 758 } 759 760 // LoginReply is used to reply to the Login command. 761 type LoginReply struct { 762 IsAdmin bool `json:"isadmin"` // Set if user is an admin 763 UserID string `json:"userid"` // User id 764 Email string `json:"email"` // User email 765 Username string `json:"username"` // Username 766 PublicKey string `json:"publickey"` // Active public key 767 PaywallAddress string `json:"paywalladdress"` // Registration paywall address 768 PaywallAmount uint64 `json:"paywallamount"` // Registration paywall amount in atoms 769 PaywallTxNotBefore int64 `json:"paywalltxnotbefore"` // Minimum timestamp for paywall tx 770 PaywallTxID string `json:"paywalltxid"` // Paywall payment tx ID 771 ProposalCredits uint64 `json:"proposalcredits"` // Number of the proposal credits the user has available to spend 772 LastLoginTime int64 `json:"lastlogintime"` // Unix timestamp of last login date 773 SessionMaxAge int64 `json:"sessionmaxage"` // Unix timestamp of session max age 774 TOTPVerified bool `json:"totpverified"` // Whether current totp secret has been verified with 775 } 776 777 // Logout attempts to log the user out. 778 type Logout struct{} 779 780 // LogoutReply indicates whether the Logout command was success or not. 781 type LogoutReply struct{} 782 783 // Me asks the server to return pertinent user information. 784 // 785 // Note that MeReply is not present because LoginReply is reused 786 // for this endpoint. 787 type Me struct{} 788 789 // UserRegistrationPayment is used to request the server to check for the 790 // provided transaction on the Decred blockchain and verify that it 791 // satisfies the requirements for a user to pay his registration fee. 792 type UserRegistrationPayment struct{} 793 794 // UserRegistrationPaymentReply is used to reply to the UserRegistrationPayment 795 // command. 796 type UserRegistrationPaymentReply struct { 797 HasPaid bool `json:"haspaid"` 798 PaywallAddress string `json:"paywalladdress"` // Registration paywall address 799 PaywallAmount uint64 `json:"paywallamount"` // Registration paywall amount in atoms 800 PaywallTxNotBefore int64 `json:"paywalltxnotbefore"` // Minimum timestamp for paywall tx 801 } 802 803 // UserProposalPaywall is used to request proposal paywall details from the 804 // server that the user needs in order to purchase paywall credits. 805 type UserProposalPaywall struct{} 806 807 // UserProposalPaywallReply is used to reply to the UserProposalPaywall 808 // command. 809 type UserProposalPaywallReply struct { 810 CreditPrice uint64 `json:"creditprice"` // Cost per proposal credit in atoms 811 PaywallAddress string `json:"paywalladdress"` // Proposal paywall address 812 PaywallTxNotBefore int64 `json:"paywalltxnotbefore"` // Minimum timestamp for paywall tx 813 } 814 815 // UserProposalPaywallTx is used to request payment details for a pending 816 // proposal paywall payment. 817 type UserProposalPaywallTx struct{} 818 819 // UserProposalPaywallTxReply is used to reply to the ProposalPaywallPayment 820 // command. 821 type UserProposalPaywallTxReply struct { 822 TxID string `json:"txid"` // Transaction ID 823 TxAmount uint64 `json:"amount"` // Transaction amount in atoms 824 Confirmations uint64 `json:"confirmations"` // Number of block confirmations 825 } 826 827 // UserProposalCredits is used to request a list of all the user's unspent 828 // proposal credits and a list of all of the user's spent proposal credits. 829 // A spent credit means that the credit was used to submit a proposal. Spent 830 // credits have a proposal censorship token associated with them to signify 831 // that they have been spent. 832 type UserProposalCredits struct{} 833 834 // UserProposalCreditsReply is used to reply to the UserProposalCredits command. 835 // It contains unspent credits that the user purchased but did not yet use, and 836 // the credits the user already spent to submit proposals. 837 type UserProposalCreditsReply struct { 838 UnspentCredits []ProposalCredit `json:"unspentcredits"` 839 SpentCredits []ProposalCredit `json:"spentcredits"` 840 } 841 842 // UserPaymentsRescan allows an admin to rescan a user's paywall address to 843 // check for any payments that may have been missed by paywall polling. Any 844 // proposal credits that are created as a result of the rescan are returned in 845 // the UserPaymentsRescanReply. This call isn't RESTful, but a PUT request is 846 // used since it's idempotent. 847 type UserPaymentsRescan struct { 848 UserID string `json:"userid"` // ID of user to rescan 849 } 850 851 // UserPaymentsRescanReply is used to reply to the UserPaymentsRescan command. 852 // Returns the credits that were created by the rescan. 853 type UserPaymentsRescanReply struct { 854 NewCredits []ProposalCredit `json:"newcredits"` 855 } 856 857 // NewProposal attempts to submit a new proposal. 858 // 859 // Metadata is required to include a ProposalMetadata for all proposal 860 // submissions. 861 // 862 // Signature is the signature of the proposal merkle root. The merkle root 863 // contains the ordered files and metadata digests. The file digests are first 864 // in the ordering. 865 // 866 // This request is NO LONGER SUPPORTED. 867 type NewProposal struct { 868 Files []File `json:"files"` // Proposal files 869 Metadata []Metadata `json:"metadata"` // User specified metadata 870 PublicKey string `json:"publickey"` // Key used for signature. 871 Signature string `json:"signature"` // Signature of merkle root 872 } 873 874 // NewProposalReply is used to reply to the NewProposal command 875 // 876 // This request is NO LONGER SUPPORTED. 877 type NewProposalReply struct { 878 CensorshipRecord CensorshipRecord `json:"censorshiprecord"` 879 } 880 881 // ProposalsDetails is used to retrieve a proposal by it's token 882 // and by the proposal version (optional). If the version isn't specified 883 // the latest proposal version will be returned by default. Returns only 884 // vetted proposals. 885 // 886 // This request has been DEPRECATED. 887 type ProposalsDetails struct { 888 Token string `json:"token"` // Censorship token 889 Version string `json:"version,omitempty"` // Proposal version 890 } 891 892 // ProposalDetailsReply is used to reply to a proposal details command. 893 // 894 // This request has been DEPRECATED. 895 type ProposalDetailsReply struct { 896 Proposal ProposalRecord `json:"proposal"` 897 } 898 899 // BatchProposals is used to request the proposal details for each of the 900 // provided censorship tokens. The returned proposals do not include the 901 // proposal files. Returns only vetted proposals. 902 // 903 // This request has been DEPRECATED. 904 type BatchProposals struct { 905 Tokens []string `json:"tokens"` // Censorship tokens 906 } 907 908 // BatchProposalsReply is used to reply to a BatchProposals command. 909 // 910 // This request has been DEPRECATED. 911 type BatchProposalsReply struct { 912 Proposals []ProposalRecord `json:"proposals"` 913 } 914 915 // BatchVoteSummary is used to request the VoteSummary for the each of the 916 // provided censorship tokens. 917 // 918 // This request has been DEPRECATED. 919 type BatchVoteSummary struct { 920 Tokens []string `json:"tokens"` // Censorship tokens 921 } 922 923 // BatchVoteSummaryReply is used to reply to a BatchVoteSummary command. 924 // 925 // This request has been DEPRECATED. 926 type BatchVoteSummaryReply struct { 927 BestBlock uint64 `json:"bestblock"` // Current block height 928 Summaries map[string]VoteSummary `json:"summaries"` // [token]VoteSummary 929 } 930 931 // SetProposalStatus is used to change the status of a proposal. Only admins 932 // have the ability to change a proposal's status. Some status changes, such 933 // as censoring a proposal, require the StatusChangeMessage to be populated 934 // with the reason for the status change. 935 // 936 // This request is NO LONGER SUPPORTED. 937 type SetProposalStatus struct { 938 Token string `json:"token"` // Proposal token 939 ProposalStatus PropStatusT `json:"proposalstatus"` // New status 940 StatusChangeMessage string `json:"statuschangemessage,omitempty"` // Message associated to the status change 941 Signature string `json:"signature"` // Signature of Token+string(ProposalStatus)+StatusChangeMessage 942 PublicKey string `json:"publickey"` // Signature pubkey 943 } 944 945 // SetProposalStatusReply is used to reply to a SetProposalStatus command. 946 // 947 // This request is NO LONGER SUPPORTED. 948 type SetProposalStatusReply struct { 949 Proposal ProposalRecord `json:"proposal"` 950 } 951 952 // GetAllVetted retrieves vetted proposals; the maximum number returned is 953 // dictated by ProposalListPageSize. 954 // 955 // This command optionally takes either a Before or After parameter, which 956 // specify a proposal's censorship token. If After is specified, the "page" 957 // returned starts after the provided censorship token, when sorted in reverse 958 // chronological order. A simplified example is shown below. 959 // 960 // input: [5,4,3,2,1] 961 // after=3 962 // output: [2,1] 963 // 964 // If Before is specified, the "page" returned starts before the provided 965 // proposal censorship token, when sorted in reverse chronological order. 966 // 967 // This request is DEPRECATED. The Before and After arguments are NO LONGER 968 // SUPPORTED. This route will only return a single page of vetted tokens. The 969 // records API InventoryOrdered command should be used instead. 970 type GetAllVetted struct { 971 Before string `schema:"before"` 972 After string `schema:"after"` 973 } 974 975 // GetAllVettedReply is used to reply with a list of vetted proposals. 976 // 977 // This request is DEPRECATED. 978 type GetAllVettedReply struct { 979 Proposals []ProposalRecord `json:"proposals"` 980 } 981 982 // Policy returns a struct with various maxima. The client shall observe the 983 // maxima. 984 type Policy struct{} 985 986 // PolicyReply is used to reply to the policy command. It returns 987 // the file upload restrictions set for Politeia. 988 type PolicyReply struct { 989 MinPasswordLength uint `json:"minpasswordlength"` 990 MinUsernameLength uint `json:"minusernamelength"` 991 MaxUsernameLength uint `json:"maxusernamelength"` 992 UsernameSupportedChars []string `json:"usernamesupportedchars"` 993 ProposalListPageSize uint `json:"proposallistpagesize"` 994 UserListPageSize uint `json:"userlistpagesize"` 995 MaxImages uint `json:"maximages"` 996 MaxImageSize uint `json:"maximagesize"` 997 MaxMDs uint `json:"maxmds"` 998 MaxMDSize uint `json:"maxmdsize"` 999 ValidMIMETypes []string `json:"validmimetypes"` 1000 MinProposalNameLength uint `json:"minproposalnamelength"` 1001 MaxProposalNameLength uint `json:"maxproposalnamelength"` 1002 PaywallEnabled bool `json:"paywallenabled"` 1003 ProposalNameSupportedChars []string `json:"proposalnamesupportedchars"` 1004 MaxCommentLength uint `json:"maxcommentlength"` 1005 BackendPublicKey string `json:"backendpublickey"` 1006 TokenPrefixLength int `json:"tokenprefixlength"` 1007 BuildInformation []string `json:"buildinformation"` 1008 IndexFilename string `json:"indexfilename"` 1009 MinLinkByPeriod int64 `json:"minlinkbyperiod"` 1010 MaxLinkByPeriod int64 `json:"maxlinkbyperiod"` 1011 MinVoteDuration uint32 `json:"minvoteduration"` 1012 MaxVoteDuration uint32 `json:"maxvoteduration"` 1013 PaywallConfirmations uint64 `json:"paywallconfirmations"` 1014 } 1015 1016 // VoteOption describes a single vote option. 1017 type VoteOption struct { 1018 Id string `json:"id"` // Single unique word identifying vote (e.g. yes) 1019 Description string `json:"description"` // Longer description of the vote. 1020 Bits uint64 `json:"bits"` // Bits used for this option 1021 } 1022 1023 // Vote represents the vote options for vote that is identified by its token. 1024 type Vote struct { 1025 Token string `json:"token"` // Token that identifies vote 1026 Mask uint64 `json:"mask"` // Valid votebits 1027 Duration uint32 `json:"duration"` // Duration in blocks 1028 QuorumPercentage uint32 `json:"quorumpercentage"` // Percent of eligible votes required for quorum 1029 PassPercentage uint32 `json:"passpercentage"` // Percent of total votes required to pass 1030 Options []VoteOption `json:"options"` // Vote options 1031 } 1032 1033 // ActiveVote obtains all proposals that have active votes. 1034 // 1035 // This request is NO LONGER SUPPORTED. 1036 type ActiveVote struct{} 1037 1038 // ProposalVoteTuple is the proposal, vote and vote details. 1039 type ProposalVoteTuple struct { 1040 Proposal ProposalRecord `json:"proposal"` // Proposal 1041 StartVote StartVote `json:"startvote"` // Vote bits and mask 1042 StartVoteReply StartVoteReply `json:"startvotereply"` // Eligible tickets and other details 1043 } 1044 1045 // ActiveVoteReply returns all proposals that have active votes. 1046 // 1047 // This request is DEPRECATED. 1048 type ActiveVoteReply struct { 1049 Votes []ProposalVoteTuple `json:"votes"` // Active votes 1050 } 1051 1052 // plugin commands 1053 1054 // AuthorizeVote is used to indicate that a proposal has been finalized and 1055 // is ready to be voted on. The signature and public key are from the 1056 // proposal author. The author can revoke a previously sent vote authorization 1057 // by setting the Action field to revoke. 1058 // 1059 // This request is NO LONGER SUPPORTED. 1060 type AuthorizeVote struct { 1061 Action string `json:"action"` // Authorize or revoke 1062 Token string `json:"token"` // Proposal token 1063 Signature string `json:"signature"` // Signature of token+version+action 1064 PublicKey string `json:"publickey"` // Key used for signature 1065 } 1066 1067 // AuthorizeVoteReply returns a receipt if the action was successfully 1068 // executed. 1069 // 1070 // This request is NO LONGER SUPPORTED. 1071 type AuthorizeVoteReply struct { 1072 Action string `json:"action"` // Authorize or revoke 1073 Receipt string `json:"receipt"` // Server signature of client signature 1074 } 1075 1076 // StartVote starts the voting process for a proposal. 1077 // 1078 // This request is NO LONGER SUPPORTED. 1079 type StartVote struct { 1080 PublicKey string `json:"publickey"` // Key used for signature. 1081 Vote Vote `json:"vote"` // Vote 1082 Signature string `json:"signature"` // Signature of Votehash 1083 } 1084 1085 // StartVoteReply returns the eligible ticket pool. 1086 // 1087 // This request is NO LONGER SUPPORTED. 1088 type StartVoteReply struct { 1089 StartBlockHeight string `json:"startblockheight"` // Block height 1090 StartBlockHash string `json:"startblockhash"` // Block hash 1091 EndHeight string `json:"endheight"` // Height of vote end 1092 EligibleTickets []string `json:"eligibletickets"` // Valid voting tickets 1093 } 1094 1095 // CastVote is a signed vote. 1096 type CastVote struct { 1097 Token string `json:"token"` // Proposal ID 1098 Ticket string `json:"ticket"` // Ticket ID 1099 VoteBit string `json:"votebit"` // Vote bit that was selected, this is encode in hex 1100 Signature string `json:"signature"` // Signature of Token+Ticket+VoteBit 1101 } 1102 1103 // CastVoteReply is the answer to the CastVote command. The Error and 1104 // ErrorStatus fields will only be populated if something went wrong while 1105 // attempting to cast the vote. 1106 type CastVoteReply struct { 1107 ClientSignature string `json:"clientsignature"` // Signature that was sent in 1108 Signature string `json:"signature"` // Signature of the ClientSignature 1109 Error string `json:"error"` // Error status message 1110 ErrorStatus decredplugin.ErrorStatusT `json:"errorstatus,omitempty"` // Error status code 1111 } 1112 1113 // Ballot is a batch of votes that are sent to the server. 1114 // 1115 // This request has been DEPRECATED. 1116 type Ballot struct { 1117 Votes []CastVote `json:"votes"` 1118 } 1119 1120 // BallotReply is a reply to a batched list of votes. 1121 // 1122 // This request has been DEPRECATED. 1123 type BallotReply struct { 1124 Receipts []CastVoteReply `json:"receipts"` 1125 } 1126 1127 // VoteResults retrieves a single proposal vote results from the server. If the 1128 // voting period has not yet started for the given proposal a reply is returned 1129 // with all fields set to their zero value. 1130 // 1131 // This request has been DEPRECATED. 1132 type VoteResults struct{} 1133 1134 // VoteResultsReply returns the original proposal vote and the associated cast 1135 // votes. 1136 // 1137 // This request has been DEPRECATED. 1138 type VoteResultsReply struct { 1139 StartVote StartVote `json:"startvote"` // Original vote 1140 CastVotes []CastVote `json:"castvotes"` // Vote results 1141 StartVoteReply StartVoteReply `json:"startvotereply"` // Eligible tickets and other details 1142 } 1143 1144 // Comment is the structure that describes the full server side content. It 1145 // includes server side meta-data as well. 1146 type Comment struct { 1147 // Data generated by client 1148 Token string `json:"token"` // Censorship token 1149 ParentID string `json:"parentid"` // Parent comment ID 1150 Comment string `json:"comment"` // Comment 1151 Signature string `json:"signature"` // Client Signature of Token+ParentID+Comment 1152 PublicKey string `json:"publickey"` // Pubkey used for Signature 1153 1154 // Metadata generated by decred plugin 1155 CommentID string `json:"commentid"` // Comment ID 1156 Receipt string `json:"receipt"` // Server signature of the client Signature 1157 Timestamp int64 `json:"timestamp"` // Received UNIX timestamp 1158 ResultVotes int64 `json:"resultvotes"` // Vote score 1159 Upvotes uint64 `json:"upvotes,omitempty"` // Pro votes 1160 Downvotes uint64 `json:"downvotes,omitempty"` // Contra votes 1161 Censored bool `json:"censored"` // Has this comment been censored 1162 1163 // Metadata generated by www 1164 UserID string `json:"userid"` // User id 1165 Username string `json:"username"` // Username 1166 } 1167 1168 // NewComment sends a comment from a user to a specific proposal. Note that 1169 // the user is implied by the session. A parent ID of 0 indicates that the 1170 // comment does not have a parent. A non-zero parent ID indicates that the 1171 // comment is a reply to an existing comment. 1172 // 1173 // This request is NO LONGER SUPPORTED. 1174 type NewComment struct { 1175 Token string `json:"token"` // Censorship token 1176 ParentID string `json:"parentid"` // Parent comment ID 1177 Comment string `json:"comment"` // Comment 1178 Signature string `json:"signature"` // Client Signature of Token+ParentID+Comment 1179 PublicKey string `json:"publickey"` // Pubkey used for Signature 1180 } 1181 1182 // NewCommentReply returns the site generated Comment ID or an error if 1183 // something went wrong. 1184 // 1185 // This request is NO LONGER SUPPORTED. 1186 type NewCommentReply struct { 1187 Comment Comment `json:"comment"` // Comment + receipt 1188 } 1189 1190 // GetComments retrieve all comments for a given proposal. 1191 // 1192 // This request is NO LONGER SUPPORTED. 1193 type GetComments struct { 1194 Token string `json:"token"` // Censorship token 1195 } 1196 1197 // GetCommentsReply returns the provided number of comments. 1198 // 1199 // This request is NO LONGER SUPPORTED. 1200 type GetCommentsReply struct { 1201 Comments []Comment `json:"comments"` // Comments 1202 AccessTime int64 `json:"accesstime,omitempty"` // User Access Time 1203 } 1204 1205 const ( 1206 // VoteActionDown used when user votes down a comment 1207 VoteActionDown = "-1" 1208 // VoteActionUp used when user votes up a comment 1209 VoteActionUp = "1" 1210 ) 1211 1212 // LikeComment allows a user to up or down vote a comment. 1213 // 1214 // This request is NO LONGER SUPPORTED. 1215 type LikeComment struct { 1216 Token string `json:"token"` // Censorship token 1217 CommentID string `json:"commentid"` // Comment ID 1218 Action string `json:"action"` // VoteActionUp or VoteActionDown above 1219 Signature string `json:"signature"` // Client Signature of Token+CommentID+Action 1220 PublicKey string `json:"publickey"` // Pubkey used for Signature 1221 } 1222 1223 // LikeCommentReply returns the current up/down vote result. 1224 // 1225 // This request is NO LONGER SUPPORTED. 1226 type LikeCommentReply struct { 1227 // XXX we probably need a sequence numkber or something here and some sort of rate limit 1228 Total uint64 `json:"total"` // Total number of up and down votes 1229 Result int64 `json:"result"` // Current tally of likes, can be negative 1230 Upvotes uint64 `json:"upvotes,omitempty"` // Current tally of pro votes 1231 Downvotes uint64 `json:"downvotes,omitempty"` // Current tally of contra votes 1232 Receipt string `json:"receipt"` // Server signature of client signature 1233 Error string `json:"error,omitempty"` // Error if something went wrong during liking a comment 1234 } 1235 1236 // CensorComment allows an admin to censor a comment. The signature and 1237 // public key are from the admin that censored this comment. 1238 // 1239 // This request is NO LONGER SUPPORTED. 1240 type CensorComment struct { 1241 Token string `json:"token"` // Proposal censorship token 1242 CommentID string `json:"commentid"` // Comment ID 1243 Reason string `json:"reason"` // Reason the comment was censored 1244 Signature string `json:"signature"` // Client signature of Token+CommentID+Reason 1245 PublicKey string `json:"publickey"` // Pubkey used for signature 1246 } 1247 1248 // CensorCommentReply returns a receipt if the comment was successfully 1249 // censored. 1250 // 1251 // This request is NO LONGER SUPPORTED. 1252 type CensorCommentReply struct { 1253 Receipt string `json:"receipt"` // Server signature of client signature 1254 } 1255 1256 // CommentLike describes the voting action an user has given 1257 // to a comment (e.g: up or down vote) 1258 type CommentLike struct { 1259 Action string `json:"action"` // VoteActionUp or VoteActionDown above 1260 CommentID string `json:"commentid"` // Comment ID 1261 Token string `json:"token"` // Censorship token 1262 } 1263 1264 // UserCommentsLikes is a command to fetch all user vote actions 1265 // on the comments of a given proposal 1266 // 1267 // This request is NO LONGER SUPPORTED. 1268 type UserCommentsLikes struct{} 1269 1270 // UserCommentsLikesReply is a reply with all user vote actions 1271 // for the comments of a given proposal 1272 // 1273 // This request is NO LONGER SUPPORTED. 1274 type UserCommentsLikesReply struct { 1275 CommentsLikes []CommentLike `json:"commentslikes"` 1276 } 1277 1278 // VoteOptionResult is a structure that describes a VotingOption along with the 1279 // number of votes it has received 1280 type VoteOptionResult struct { 1281 Option VoteOption `json:"option"` // Vote Option 1282 VotesReceived uint64 `json:"votesreceived"` // Number of votes received by the option 1283 } 1284 1285 // VoteStatus is a command to fetch the the current vote status for a single 1286 // public proposal 1287 // 1288 // This request is DEPRECATED. 1289 type VoteStatus struct{} 1290 1291 // VoteStatusReply describes the vote status for a given proposal 1292 // 1293 // This request is DEPRECATED. 1294 type VoteStatusReply struct { 1295 Token string `json:"token"` // Censorship token 1296 Status PropVoteStatusT `json:"status"` // Vote status (finished, started, etc) 1297 TotalVotes uint64 `json:"totalvotes"` // Proposal's total number of votes 1298 OptionsResult []VoteOptionResult `json:"optionsresult"` // VoteOptionResult for each option 1299 EndHeight string `json:"endheight"` // Vote end height 1300 BestBlock string `json:"bestblock"` // Current best block height 1301 NumOfEligibleVotes int `json:"numofeligiblevotes"` // Total number of eligible votes 1302 QuorumPercentage uint32 `json:"quorumpercentage"` // Percent of eligible votes required for quorum 1303 PassPercentage uint32 `json:"passpercentage"` // Percent of total votes required to pass 1304 } 1305 1306 // GetAllVoteStatus attempts to fetch the vote status of all public propsals 1307 // 1308 // This request is DEPRECATED. 1309 type GetAllVoteStatus struct{} 1310 1311 // GetAllVoteStatusReply returns the vote status of all public proposals 1312 // 1313 // This request is DEPRECATED. 1314 type GetAllVoteStatusReply struct { 1315 VotesStatus []VoteStatusReply `json:"votesstatus"` // Vote status of all public proposals 1316 } 1317 1318 // UserDetails fetches a user's details by their id. 1319 type UserDetails struct { 1320 UserID string `json:"userid"` // User id 1321 } 1322 1323 // UserDetailsReply returns a user's details. 1324 type UserDetailsReply struct { 1325 User User `json:"user"` 1326 } 1327 1328 // ManageUser performs the given action on a user. 1329 type ManageUser struct { 1330 UserID string `json:"userid"` // User id 1331 Action UserManageActionT `json:"action"` // Action 1332 Reason string `json:"reason"` // Admin reason for action 1333 } 1334 1335 // ManageUserReply is the reply for the ManageUserReply command. 1336 type ManageUserReply struct{} 1337 1338 // EditUser edits a user's preferences. 1339 type EditUser struct { 1340 EmailNotifications *uint64 `json:"emailnotifications"` // Notify the user via emails 1341 } 1342 1343 // EditUserReply is the reply for the EditUser command. 1344 type EditUserReply struct{} 1345 1346 // User represents an individual user. 1347 type User struct { 1348 ID string `json:"id"` 1349 Email string `json:"email"` 1350 Username string `json:"username"` 1351 Admin bool `json:"isadmin"` 1352 NewUserPaywallAddress string `json:"newuserpaywalladdress"` 1353 NewUserPaywallAmount uint64 `json:"newuserpaywallamount"` 1354 NewUserPaywallTx string `json:"newuserpaywalltx"` 1355 NewUserPaywallTxNotBefore int64 `json:"newuserpaywalltxnotbefore"` 1356 NewUserPaywallPollExpiry int64 `json:"newuserpaywallpollexpiry"` 1357 NewUserVerificationToken []byte `json:"newuserverificationtoken"` 1358 NewUserVerificationExpiry int64 `json:"newuserverificationexpiry"` 1359 UpdateKeyVerificationToken []byte `json:"updatekeyverificationtoken"` 1360 UpdateKeyVerificationExpiry int64 `json:"updatekeyverificationexpiry"` 1361 ResetPasswordVerificationToken []byte `json:"resetpasswordverificationtoken"` 1362 ResetPasswordVerificationExpiry int64 `json:"resetpasswordverificationexpiry"` 1363 LastLoginTime int64 `json:"lastlogintime"` 1364 FailedLoginAttempts uint64 `json:"failedloginattempts"` 1365 Deactivated bool `json:"isdeactivated"` 1366 Locked bool `json:"islocked"` 1367 Identities []UserIdentity `json:"identities"` 1368 ProposalCredits uint64 `json:"proposalcredits"` 1369 EmailNotifications uint64 `json:"emailnotifications"` // Notify the user via emails 1370 } 1371 1372 // UserIdentity represents a user's unique identity. 1373 type UserIdentity struct { 1374 Pubkey string `json:"pubkey"` 1375 Active bool `json:"isactive"` 1376 } 1377 1378 // EditProposal attempts to edit a proposal 1379 // 1380 // Metadata is required to include a ProposalMetadata for all proposal 1381 // submissions. 1382 // 1383 // Signature is the signature of the proposal merkle root. The merkle root 1384 // contains the ordered files and metadata digests. The file digests are first 1385 // in the ordering. 1386 // 1387 // This request is NO LONGER SUPPORTED. 1388 type EditProposal struct { 1389 Token string `json:"token"` 1390 Files []File `json:"files"` 1391 Metadata []Metadata `json:"metadata"` 1392 PublicKey string `json:"publickey"` 1393 Signature string `json:"signature"` 1394 } 1395 1396 // EditProposalReply is used to reply to the EditProposal command 1397 // 1398 // This request is NO LONGER SUPPORTED. 1399 type EditProposalReply struct { 1400 Proposal ProposalRecord `json:"proposal"` 1401 } 1402 1403 // TokenInventory retrieves the censorship record tokens of all proposals in 1404 // the inventory, categorized by stage of the voting process. 1405 // 1406 // This request has been DEPRECATED. 1407 type TokenInventory struct{} 1408 1409 // TokenInventoryReply is used to reply to the TokenInventory command and 1410 // returns the tokens of all proposals in the inventory. The tokens are 1411 // categorized by stage of the voting process and sorted according to the 1412 // rules listed below. Unvetted proposal tokens are only returned to admins. 1413 // 1414 // Sorted by record timestamp in descending order: 1415 // Pre, Abandonded, Unreviewed, Censored 1416 // 1417 // Sorted by voting period end block height in descending order: 1418 // Active, Approved, Rejected 1419 // 1420 // This request has been DEPRECATED. 1421 type TokenInventoryReply struct { 1422 // Vetted 1423 Pre []string `json:"pre"` // Tokens of all props that are pre-vote 1424 Active []string `json:"active"` // Tokens of all props with an active voting period 1425 Approved []string `json:"approved"` // Tokens of all props that have been approved by a vote 1426 Rejected []string `json:"rejected"` // Tokens of all props that have been rejected by a vote 1427 Abandoned []string `json:"abandoned"` // Tokens of all props that have been abandoned 1428 1429 // Unvetted 1430 Unreviewed []string `json:"unreviewed"` // Tokens of all unreviewed props 1431 Censored []string `json:"censored"` // Tokens of all censored props 1432 } 1433 1434 // Websocket commands 1435 const ( 1436 WSCError = "error" 1437 WSCPing = "ping" 1438 WSCSubscribe = "subscribe" 1439 ) 1440 1441 // WSHeader is required to be sent before any other command. The point is to 1442 // make decoding easier without too much magic. E.g. a ping command 1443 // WSHeader<ping>WSPing<timestamp> 1444 type WSHeader struct { 1445 Command string `json:"command"` // Following command 1446 ID string `json:"id,omitempty"` // Client setable client id 1447 } 1448 1449 // WSError is a generic websocket error. It returns in ID the client side id 1450 // and all errors it encountered in Errors. 1451 type WSError struct { 1452 Command string `json:"command,omitempty"` // Command from client 1453 ID string `json:"id,omitempty"` // Client set client id 1454 Errors []string `json:"errors"` // Errors returned by server 1455 } 1456 1457 // WSSubscribe is a client side push to tell the server what RPCs it wishes to 1458 // subscribe to. 1459 type WSSubscribe struct { 1460 RPCS []string `json:"rpcs"` // Commands that the client wants to subscribe to 1461 } 1462 1463 // WSPing is a server side push to the client to see if it is still alive. 1464 type WSPing struct { 1465 Timestamp int64 `json:"timestamp"` // Server side timestamp 1466 } 1467 1468 // SetTOTP attempts to set a TOTP key for the chosen TOTP type (Basic/UFI2 etc). 1469 // When the user issues this request, the server generates a new key pair for 1470 // them and returns the key/image that will allow them to save it to their 1471 // TOTP app of choice. The server saves the generated TOTP secret in the 1472 // userdb user information blob. 1473 // If the user already has a TOTP set, they must also add a code generated from 1474 // the currently set secret. 1475 type SetTOTP struct { 1476 Type TOTPMethodT `json:"type"` 1477 Code string `json:"code"` 1478 } 1479 1480 // SetTOTPReply returns the generated key and image that are used to add 1481 // the key pair to the TOTP app of choice. 1482 type SetTOTPReply struct { 1483 Key string `json:"key"` 1484 Image string `json:"image"` // Base64 encoded PNG 1485 } 1486 1487 // VerifyTOTP must be used by a user before their TOTP is ready to use. Once 1488 // receiving the key/image from SetTOTP they can add it to their TOTP app. 1489 // Upon adding it to their TOTP app, they can generate new TOTP codes at will. 1490 type VerifyTOTP struct { 1491 Code string `json:"code"` 1492 } 1493 1494 // VerifyTOTPReply will return an empty reply if it was successfully confirmed 1495 // with no errors. 1496 type VerifyTOTPReply struct { 1497 }