From 38bcc1bc1cebd795140ac205fc4fa133ec56b1b2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 13 Aug 2024 15:11:24 +0000 Subject: [PATCH] fix vote credit redeem --- .../endpoints/redeem_vote_credits/route.go | 2 +- types/vote.go | 14 ++++---- votes/votecredits.go | 34 ++++++++++++++++--- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/routes/votes/endpoints/redeem_vote_credits/route.go b/routes/votes/endpoints/redeem_vote_credits/route.go index 3080e41a..44d3c283 100644 --- a/routes/votes/endpoints/redeem_vote_credits/route.go +++ b/routes/votes/endpoints/redeem_vote_credits/route.go @@ -57,7 +57,7 @@ func Route(d uapi.RouteData, r *http.Request) uapi.HttpResponse { } } - votesParam := chi.URLParam(r, "votes") + votesParam := r.URL.Query().Get("votes") votesInt, err := strconv.Atoi(votesParam) diff --git a/types/vote.go b/types/vote.go index 8197133d..eeecb402 100644 --- a/types/vote.go +++ b/types/vote.go @@ -26,12 +26,13 @@ type EntityVote struct { // Vote Info type VoteInfo struct { - PerUser int `json:"per_user" description:"The amount of votes a single vote creates on this entity"` - VoteTime uint16 `json:"vote_time" description:"The amount of time in hours until a user can vote again"` - VoteCredits bool `json:"vote_credits" description:"Whether or not the entity supports vote credits"` - MultipleVotes bool `json:"multiple_votes" description:"Whether or not the entity supports multiple votes per time interval"` - SupportsUpvotes bool `json:"supports_upvotes" description:"Whether or not the entity supports upvotes"` - SupportsDownvotes bool `json:"supports_downvotes" description:"Whether or not the entity supports downvotes"` + PerUser int `json:"per_user" description:"The amount of votes a single vote creates on this entity"` + VoteTime uint16 `json:"vote_time" description:"The amount of time in hours until a user can vote again"` + VoteCredits bool `json:"vote_credits" description:"Whether or not the entity supports vote credits"` + MultipleVotes bool `json:"multiple_votes" description:"Whether or not the entity supports multiple votes per time interval"` + SupportsUpvotes bool `json:"supports_upvotes" description:"Whether or not the entity supports upvotes"` + SupportsDownvotes bool `json:"supports_downvotes" description:"Whether or not the entity supports downvotes"` + SupportsPartialVoteCreditsRedeem bool `json:"supports_partial_vote_credits_redeem" description:"Whether or not the entity supports partial vote credit redemption"` } // Stores the hours, minutes and seconds until the user can vote again @@ -71,6 +72,7 @@ type VoteCreditTierRedeemSummary struct { Votes int `json:"votes" description:"The amount of votes the entity has"` SlabOverview []int `json:"slab_overview" description:"Slab-based overview with each index, i, representing the amount of votes in Tiers[i]"` TotalCredits int `json:"total_credits" description:"The total amount of credits the user would get, in cents"` + VoteInfo *VoteInfo `json:"vote_info" description:"Some information about the vote"` } // Represents a vote credit redeem log diff --git a/votes/votecredits.go b/votes/votecredits.go index 028d07c6..b2bc50c9 100644 --- a/votes/votecredits.go +++ b/votes/votecredits.go @@ -45,6 +45,12 @@ func EntityGetVoteCreditsSummary( return nil, fmt.Errorf("could not fetch vote count: %w", err) } + voteInfo, err := EntityVoteInfo(ctx, c, targetId, targetType) + + if err != nil { + return nil, fmt.Errorf("could not fetch vote info: %w", err) + } + slabOverview := SlabSplitVotes(voteCount, vcts) totalCredits := SlabCalculateCredits(vcts, slabOverview) @@ -53,6 +59,7 @@ func EntityGetVoteCreditsSummary( Votes: voteCount, SlabOverview: slabOverview, TotalCredits: totalCredits, + VoteInfo: voteInfo, }, nil } @@ -92,6 +99,10 @@ func EntityRedeemVoteCredits( return fmt.Errorf("could not fetch vote count: %w", err) } + if !vi.SupportsPartialVoteCreditsRedeem { + votesToRedeem = voteCount // If the entity does not support partial vote credit redemption, then redeem all votes + } + // Check if the votes to redeem exceeds the total votes to protect against malicious input for votes to redeem if votesToRedeem > voteCount { return errors.New("votes to redeem exceeds total votes") @@ -105,16 +116,31 @@ func EntityRedeemVoteCredits( } var id pgtype.UUID - err = c.QueryRow(ctx, "INSERT INTO entity_vote_redeem_logs (target_id, target_id, credits) VALUES ($1, $2, $3) RETURNING id", targetId, targetType, totalCredits).Scan(&id) + err = c.QueryRow(ctx, "INSERT INTO entity_vote_redeem_logs (target_id, target_type, credits) VALUES ($1, $2, $3) RETURNING id", targetId, targetType, totalCredits).Scan(&id) if err != nil { return fmt.Errorf("could not log vote credit redemption: %w", err) } - _, err = c.Exec(ctx, "UPDATE entity_votes SET credit_redeem = $1, void = true, void_reason = 'Vote credits redeemed' WHERE target_id = $2 AND target_type = $3 AND void = false LIMIT $4", id, targetId, targetType, votesToRedeem) + if vi.SupportsPartialVoteCreditsRedeem { + var ids []pgtype.UUID + err = c.QueryRow(ctx, "SELECT array(SELECT itag FROM entity_votes WHERE target_id = $1 AND target_type = $2 AND void = false ORDER BY created_at ASC LIMIT $3)", targetId, targetType, votesToRedeem).Scan(&ids) - if err != nil { - return fmt.Errorf("could not redeem vote credits: %w", err) + if err != nil { + return fmt.Errorf("could not fetch vote ids: %w", err) + } + + _, err = c.Exec(ctx, "UPDATE entity_votes SET credit_redeem = $1, void = true, void_reason = 'Vote credits redeemed' WHERE itag = ANY($2)", id, ids) + + if err != nil { + return fmt.Errorf("could not redeem vote credits: %w", err) + } + } else { + _, err = c.Exec(ctx, "UPDATE entity_votes SET credit_redeem = $1, void = true, void_reason = 'Vote credits redeemed' WHERE target_id = $2 AND target_type = $3 AND void = false", id, targetId, targetType) + + if err != nil { + return fmt.Errorf("could not redeem vote credits: %w", err) + } } return nil