Exemplo n.º 1
0
 public UpdatePatreonInfoJob(ILogger <UpdatePatreonInfoJob> logger,
                             IHttpClientFactory httpClientFactory,
                             IOptions <PatreonSettings> patreonSettings,
                             UserManager <ApplicationUser> userManager,
                             IRepository <PatreonToken> tokenRepository,
                             IRepository <AccountSubscription> subscriptionRepository,
                             IUnitOfWork unitOfWork) : base(logger)
 {
     _httpClientFactory      = httpClientFactory;
     _userManager            = userManager;
     _unitOfWork             = unitOfWork;
     _tokenRepository        = tokenRepository;
     _subscriptionRepository = subscriptionRepository;
     _patreonSettings        = patreonSettings.Value;
 }
Exemplo n.º 2
0
 public PatreonController(
     IHttpContextAccessor contextAccessor,
     UserManager <ApplicationUser> userManager,
     IRepository <PatreonToken> repository,
     IUnitOfWork unitOfWork,
     ILogger <PatreonController> logger, IHttpClientFactory httpClientFactory,
     IOptions <PatreonSettings> patreonSettings,
     IOptions <AppSettings> appSettings) : base(contextAccessor, userManager, logger)
 {
     _repository        = repository;
     _unitOfWork        = unitOfWork;
     _httpClientFactory = httpClientFactory;
     _patreonSettings   = patreonSettings.Value;
     _appSettings       = appSettings.Value;
 }
        private async Task <string> CheckSignature(PatreonSettings settings)
        {
            if (!HttpContext.Request.Headers.TryGetValue("X-Patreon-Signature", out StringValues header) ||
                header.Count != 1)
            {
                throw new HttpResponseException()
                      {
                          Value = new BasicJSONErrorResult("Invalid request", "Missing X-Patreon-Signature header").ToString()
                      };
            }

            var actualSignature = header[0];

            if (settings == null || string.IsNullOrEmpty(settings.WebhookSecret))
            {
                throw new HttpResponseException()
                      {
                          Status = StatusCodes.Status500InternalServerError,
                          Value  = new BasicJSONErrorResult("Server configuration error", "Patreon webhook is not configured")
                                   .ToString()
                      };
            }

            var readBody = await Request.ReadBodyAsync();

            var rawPayload = readBody.Buffer.ToArray();

            var neededSignature = Convert.ToHexString(new HMACMD5(Encoding.UTF8.GetBytes(settings.WebhookSecret))
                                                      .ComputeHash(rawPayload)).ToLowerInvariant();

            if (!SecurityHelpers.SlowEquals(neededSignature, actualSignature))
            {
                logger.LogWarning("Patreon webhook signature didn't match expected value");
                throw new HttpResponseException()
                      {
                          Status = StatusCodes.Status403Forbidden,
                          Value  = new BasicJSONErrorResult("Invalid signature",
                                                            "Payload signature does not match expected value").ToString()
                      };
            }

            return(Encoding.UTF8.GetString(rawPayload));
        }
        public static RewardGroup ShouldBeInGroupForPatron(Patron?patron, PatreonSettings settings)
        {
            if (settings == null)
            {
                throw new ArgumentException("patreon settings is null");
            }

            if (patron == null || patron.Suspended == true)
            {
                return(RewardGroup.None);
            }

            if (patron.RewardId == settings.VipRewardId)
            {
                return(RewardGroup.VIP);
            }

            if (patron.RewardId == settings.DevbuildsRewardId)
            {
                return(RewardGroup.DevBuild);
            }

            return(RewardGroup.None);
        }
        /// <summary>
        ///   Gets all patrons of the active campaign
        /// </summary>
        /// <param name="settings">Where to get the campaign from</param>
        /// <param name="cancellationToken">Supports canceling this while waiting</param>
        /// <returns>API response with all the patron objects</returns>
        public async Task <List <PatronMemberInfo> > GetPatrons(PatreonSettings settings,
                                                                CancellationToken cancellationToken)
        {
            // ReSharper disable once StringLiteralTypo
            var url =
                $"https://www.patreon.com/api/oauth2/api/campaigns/{settings.CampaignId}/pledges?include=patron.null," +
                "reward&fields%5Bpledge%5D=status,currency,amount_cents,declined_since";

            var result = new List <PatronMemberInfo>();

            while (!string.IsNullOrEmpty(url))
            {
                var response = await client.GetFromJsonAsync <PatreonAPIListResponse>(url, cancellationToken);

                if (response == null)
                {
                    throw new PatreonAPIDataException("failed to deserialize response from patreon API");
                }

                foreach (var data in response.Data)
                {
                    if (data.Type != "pledge")
                    {
                        continue;
                    }

                    var patronRelationship = data.Relationships?.Patron;

                    if (patronRelationship?.Data == null)
                    {
                        throw new PatreonAPIDataException("Pledge relationship to patron doesn't exist");
                    }

                    var userData =
                        response.FindIncludedObject(patronRelationship.Data.Id, patronRelationship.Data.Type);

                    if (userData == null)
                    {
                        throw new PatreonAPIDataException("Failed to find pledge's related user object");
                    }

                    var rewardRelationship = data.Relationships?.Reward;

                    if (rewardRelationship == null)
                    {
                        throw new PatreonAPIDataException(
                                  "Pledge relationship to reward data is not included for user");
                    }

                    // This happens if the user has not selected a reward
                    // TODO: would be nice to log this problem here as we should let the patron know they need to
                    // select a reward
                    if (rewardRelationship.Data == null)
                    {
                        continue;
                    }

                    var rewardData =
                        response.FindIncludedObject(rewardRelationship.Data.Id, rewardRelationship.Data.Type);

                    if (rewardData == null)
                    {
                        throw new PatreonAPIDataException("Failed to find pledge's related reward object");
                    }

                    result.Add(new PatronMemberInfo()
                    {
                        Pledge = data,
                        User   = userData,
                        Reward = rewardData,
                    });
                }

                // Pagination
                if (response.Links != null && response.Links.TryGetValue("next", out string?nextUrl))
                {
                    url = nextUrl;
                }
                else
                {
                    // No more pages time to break the loop
                    url = null;
                }
            }

            return(result);
        }
 public PatreonCreatorAPI(PatreonSettings settings) : this(settings.CreatorToken)
 {
 }