mirror of
https://github.com/ente-io/ente.git
synced 2025-06-09 10:29:35 +00:00
85 lines
3.4 KiB
Go
85 lines
3.4 KiB
Go
package storagebonus
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"github.com/ente-io/museum/ente"
|
|
"net/http"
|
|
|
|
entity "github.com/ente-io/museum/ente/storagebonus"
|
|
"github.com/ente-io/stacktrace"
|
|
)
|
|
|
|
const (
|
|
maxReferralChangeAllowed = 3
|
|
)
|
|
|
|
// Add context as first parameter in all methods in this file
|
|
|
|
// GetCode returns the storagebonus code for the given userID
|
|
func (r *Repository) GetCode(ctx context.Context, userID int64) (*string, error) {
|
|
var code *string
|
|
err := r.DB.QueryRowContext(ctx, "SELECT code FROM referral_codes WHERE user_id = $1 and is_active = TRUE", userID).Scan(&code)
|
|
return code, stacktrace.Propagate(err, "failed to get storagebonus code for user %d", userID)
|
|
}
|
|
|
|
// InsertCode for the given userID
|
|
func (r *Repository) InsertCode(ctx context.Context, userID int64, code string) error {
|
|
_, err := r.DB.ExecContext(ctx, "INSERT INTO referral_codes (user_id, code) VALUES ($1, $2)", userID, code)
|
|
if err != nil {
|
|
if err.Error() == "pq: duplicate key value violates unique constraint \"referral_codes_pkey\"" {
|
|
return stacktrace.Propagate(entity.CodeAlreadyExistsErr, "duplicate storagebonus code for user %d", userID)
|
|
}
|
|
return stacktrace.Propagate(err, "failed to insert storagebonus code for user %d", userID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AddNewCode and mark the old one as inactive for a given userID.
|
|
// Note: This method is not being used in the initial MVP as we don't allow user to change the storagebonus
|
|
// code
|
|
func (r *Repository) AddNewCode(ctx context.Context, userID int64, code string, isAdminEdit bool) error {
|
|
// check current referral code count
|
|
var count int
|
|
err := r.DB.QueryRowContext(ctx, "SELECT COALESCE(COUNT(*),0) FROM referral_codes WHERE user_id = $1", userID).Scan(&count)
|
|
if err != nil {
|
|
return stacktrace.Propagate(err, "failed to get storagebonus code count for user %d", userID)
|
|
}
|
|
if !isAdminEdit && count > maxReferralChangeAllowed {
|
|
return stacktrace.Propagate(&ente.ApiError{
|
|
Code: "REFERRAL_CHANGE_LIMIT_REACHED",
|
|
Message: fmt.Sprintf("max referral code change limit %d reached", maxReferralChangeAllowed),
|
|
HttpStatusCode: http.StatusTooManyRequests,
|
|
}, "max referral code change limit reached for user %d", userID)
|
|
}
|
|
// check if code already exists
|
|
var existCount int
|
|
err = r.DB.QueryRowContext(ctx, "SELECT COALESCE(COUNT(*),0) FROM referral_codes WHERE code = $1", code).Scan(&existCount)
|
|
if err != nil {
|
|
return stacktrace.Propagate(err, "failed to check if code already exists for user %d", userID)
|
|
}
|
|
if existCount > 0 {
|
|
return stacktrace.Propagate(entity.CodeAlreadyExistsErr, "storagebonus code %s already exists", code)
|
|
}
|
|
_, err = r.DB.ExecContext(ctx, "UPDATE referral_codes SET is_active = FALSE WHERE user_id = $1", userID)
|
|
if err != nil {
|
|
return stacktrace.Propagate(err, "failed to update remove existing code code for user %d", userID)
|
|
}
|
|
return r.InsertCode(ctx, userID, code)
|
|
}
|
|
|
|
// GetUserIDByCode returns the userID for the given storagebonus code. The method will also return the userID
|
|
// if the code is inactive.
|
|
func (r *Repository) GetUserIDByCode(ctx context.Context, code string) (*int64, error) {
|
|
var userID int64
|
|
err := r.DB.QueryRowContext(ctx, "SELECT user_id FROM referral_codes WHERE code = $1", code).Scan(&userID)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, stacktrace.Propagate(entity.InvalidCodeErr, "code %s not found", code)
|
|
}
|
|
return nil, err
|
|
}
|
|
return &userID, nil
|
|
}
|