public async Task SaveSetting <T>(Action <T> updateAction)
        {
            using (var connection = new ConScope(_dataService))
                using (var transaction = await connection.BeginTransaction())
                {
                    var name = GetSettingNameAttribute(typeof(T));

                    var existing = await GetSetting <T>();

                    updateAction(existing);

                    var settingValue = _settingsSerializer.Serialize(existing);

                    var setting = await connection.Connection.SingleAsync(connection.Connection.From <SettingV1>().Where(x => x.Name == name));

                    if (setting == null)
                    {
                        setting = new SettingV1 {
                            Name = name, Settings = settingValue
                        };
                        await connection.Connection.SaveAsync(setting);
                    }
                    else
                    {
                        setting.Settings = settingValue;
                        await connection.Connection.UpdateAsync(setting);
                    }

                    transaction.Commit();
                }
        }
Exemple #2
0
        public async Task <Account> GetOrCreateAccount(AccountIdentification id)
        {
            using (var con = new ConScope(_dataService))
                using (var trans = await con.BeginTransaction())
                {
                    var account = await GetAccount(id);

                    if (account == null)
                    {
                        if (!id.GlobalUserId.HasValue)
                        {
                            throw new Exception("Can only auto create account when using global user id.");
                        }

                        account = new Account
                        {
                            GlobalUserId = id.GlobalUserId.Value
                        };

                        await con.Connection.SaveAsync(account);

                        trans.Commit();

                        _logger.LogInformation("Created account {AccountId} for global user {GlobalUserId", account.Id, id.GlobalUserId);
                    }

                    return(account);
                }
        }
Exemple #3
0
        public async Task <JobTask> DequeueJob()
        {
            JobV1 result;

            using (var connection = new ConScope(_dataService))
            {
                using (var transaction = await connection.BeginTransaction())
                {
                    result = await connection.Connection.SingleAsync(
                        connection.Connection.From <JobV1>()
                        .Where(x => x.Status == JobStatus.Queued)
                        .OrderBy(x => x.QueuedOn)
                        .Take(1));

                    if (result == null)
                    {
                        return(null);
                    }

                    result.Status = JobStatus.Processing;

                    await connection.Connection.UpdateAsync(result);

                    transaction.Commit();
                }
            }

            return(new JobTask
            {
                JobId = result.Id,
                Type = Type.GetType(result.JobType),
                Data = JsonConvert.DeserializeObject(result.JobData, Type.GetType(result.JobDataType), (JsonSerializerSettings)null)
            });
        }
Exemple #4
0
        public async Task MarkJobSucceeded(int jobId)
        {
            JobV1 job;

            using (var connection = new ConScope(_dataService))
            {
                using (var transaction = await connection.BeginTransaction())
                {
                    job = await connection.Connection.SingleByIdAsync <JobV1>(jobId);

                    if (job == null)
                    {
                        throw new Exception($"Invalid job id {jobId}");
                    }

                    if (job.Status != JobStatus.Processing)
                    {
                        throw new Exception($"Can't mark a job {jobId} as completed because it wasn't marked as processing.");
                    }

                    await connection.Connection.DeleteAsync(job);

                    transaction.Commit();
                }
            }

            await _jobSucceeded.Publish(this, new JobSucceededEvent(new JobTask
            {
                JobId = job.Id,
                Type = Type.GetType(job.JobType),
                Data = JsonConvert.DeserializeObject(job.JobData, Type.GetType(job.JobDataType))
            }));
        }
Exemple #5
0
        public async Task Enqueue <T, TData>(TData data) where T : IJob where TData : new()
        {
            var job = new JobV1
            {
                QueuedOn    = DateTimeOffset.UtcNow,
                JobType     = typeof(T).AssemblyQualifiedName,
                JobDataType = typeof(TData).AssemblyQualifiedName,
                JobData     = JsonConvert.SerializeObject(data)
            };

            using (var connection = new ConScope(_dataService))
            {
                using (var transaction = await connection.BeginTransaction())
                {
                    await connection.Connection.SaveAsync(job);

                    transaction.Commit();
                }
            }

            await _jobEnqueued.Publish(this, new JobEnqueuedEvent(new JobTask
            {
                JobId = job.Id,
                Type = typeof(T),
                Data = data
            }));
        }
        public async Task <Transaction> AddTransaction(Guid accountId, decimal amount, string title, string metaData, Guid?payPalOrderId)
        {
            using (var con = new ConScope(_dataService))
                using (var trans = await con.BeginTransaction())
                {
                    // Let's update the total on the account object.
                    var runningTotal = await con.Connection.SingleAsync <decimal>(
                        con.Connection.From <Transaction>()
                        .Select(x => new {
                        Sum = Sql.Sum(x.Amount)
                    }));

                    runningTotal += amount;

                    var transaction = new Transaction
                    {
                        AccountId      = accountId,
                        Date           = DateTimeOffset.UtcNow,
                        Amount         = amount,
                        CurrentBalance = runningTotal,
                        Title          = title,
                        MetaData       = metaData,
                        PayPalOrderId  = payPalOrderId
                    };

                    await con.Connection.SaveAsync(transaction);

                    await con.Connection.UpdateOnlyAsync(() => new Account { CurrentBalance = runningTotal }, x => x.Id == accountId);

                    trans.Commit();

                    return(transaction);
                }
        }
Exemple #7
0
 public async Task ReQueueProcessingJobs()
 {
     using (var connection = new ConScope(_dataService))
     {
         using (var transaction = await connection.BeginTransaction())
         {
             connection.Connection.UpdateOnly(() => new JobV1 {
                 Status = JobStatus.Queued
             },
                                              x => x.Status == JobStatus.Processing);
             transaction.Commit();
         }
     }
 }
Exemple #8
0
        public async Task CapturePendingOrder(string orderId, string payerId)
        {
            Order order;

            {
                var client  = _payPalClientProvider.BuildHttpClient();
                var request = new OrdersCaptureRequest(orderId);
                request.RequestBody(new OrderActionRequest());
                var response = await client.Execute(request);

                if (response.StatusCode != HttpStatusCode.Created)
                {
                    _logger.LogError("Invalid status code from PayPal order capture: status: {Status} response: {Response}", response.StatusCode, SerializePayPalType(response.Result <object>()));
                    throw new Exception("Invalid PayPal response");
                }

                order = response.Result <Order>();

                if (order.Status != "COMPLETED")
                {
                    _logger.LogError("The order from PayPal wasn't marked as COMPELTED: {Response}", SerializePayPalType(response.Result <object>()));
                    throw new Exception("The order from PayPal wasn't marked as COMPELTED");
                }
            }

            using (var con = new ConScope(_dataService))
                using (var trans = await con.BeginTransaction())
                {
                    var pendingOrder = con.Connection.Single <PayPalOrder>(x => x.PayPalOrderId == orderId);

                    if (pendingOrder.OrderStatus == PayPalOrderStatus.Completed)
                    {
                        throw new Exception($"Attempted to update order {orderId} as completed, but it is already marked as completed.");
                    }

                    pendingOrder.OrderStatus     = PayPalOrderStatus.Completed;
                    pendingOrder.PayPalPayerId   = payerId;
                    pendingOrder.PayPalOrderJson = SerializePayPalType(order);

                    await con.Connection.SaveAsync(pendingOrder);

                    await _transactionsService.AddTransaction(pendingOrder.AccountId, pendingOrder.Amount, "PayPal reload", pendingOrder.PayPalOrderJson, pendingOrder.Id);

                    trans.Commit();
                }
        }
Exemple #9
0
        public async Task CancelPendingOrder(string orderId)
        {
            using (var con = new ConScope(_dataService))
                using (var trans = await con.BeginTransaction())
                {
                    var pendingOrder = await con.Connection.SingleAsync <PayPalOrder>(x => x.PayPalOrderId == orderId);

                    if (pendingOrder == null)
                    {
                        throw new Exception($"No pending paypal order to cancel with id {orderId}");
                    }

                    if (pendingOrder.OrderStatus == PayPalOrderStatus.Completed)
                    {
                        throw new Exception($"The order {orderId} was already completed.");
                    }

                    await con.Connection.DeleteByIdAsync <PayPalOrder>(pendingOrder.Id);

                    trans.Commit();
                }
        }
Exemple #10
0
        public async Task RemoveProblematicJobs()
        {
            using (var connection = new ConScope(_dataService))
            {
                using (var transaction = await connection.BeginTransaction())
                {
                    var jobs = await connection.Connection.SelectAsync(connection.Connection.From <JobV1>());

                    foreach (var job in jobs)
                    {
                        try
                        {
                            var jobType = Type.GetType(job.JobType);
                            if (jobType == null)
                            {
                                throw new Exception($"Invalid job type: {job.JobType}");
                            }

                            var jobDataType = Type.GetType(job.JobDataType);
                            if (jobDataType == null)
                            {
                                throw new Exception($"Invalid job type: {job.JobDataType}");
                            }

                            JsonConvert.DeserializeObject(job.JobData, Type.GetType(job.JobDataType),
                                                          (JsonSerializerSettings)null);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "Detected problematic job, deleting");
                            await connection.Connection.DeleteByIdAsync <JobV1>(job.Id);
                        }
                    }

                    transaction.Commit();
                }
            }
        }
Exemple #11
0
        public async Task <IdentityResult> CreateAsync(User user, CancellationToken cancellationToken)
        {
            using (var connection = new ConScope(_dataService))
            {
                using (var transaction = await connection.BeginTransaction())
                {
                    var existing =
                        await connection.Connection.SingleAsync <User>(x => x.EmailNormalized == user.EmailNormalized,
                                                                       cancellationToken);

                    if (existing != null)
                    {
                        return(IdentityResult.Failed(new IdentityError
                        {
                            Description = "Email already in use."
                        }));
                    }

                    existing = await connection.Connection.SingleAsync <User>(
                        x => x.UserNameNormalized == user.UserNameNormalized, cancellationToken);

                    if (existing != null)
                    {
                        return(IdentityResult.Failed(new IdentityError
                        {
                            Description = "User name already in use."
                        }));
                    }

                    user.Id = Guid.NewGuid().ToString();
                    await connection.Connection.SaveAsync(user, token : cancellationToken);

                    transaction.Commit();

                    return(IdentityResult.Success);
                }
            }
        }