Skip to content

Commit 472a152

Browse files
authored
Merge pull request #17 from mxss/dev
v0.15.0
2 parents bbf0847 + aae74fd commit 472a152

16 files changed

+270
-67
lines changed

App/AL/Controller/Auth/JwtAuthController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ public JwtAuthController() {
107107

108108
if (queuedItem == null)
109109
return HttpResponse.Error(HttpStatusCode.NotFound, "Confirmation key is invalid");
110+
111+
if (queuedItem.email_confirmed)
112+
return HttpResponse.Error(HttpStatusCode.Forbidden, "Email is already confirmed");
110113

111114
var me = UserRepository.Find(queuedItem.user_id);
112115

App/AL/Controller/Product/ProjectProductCrudController.cs

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,22 @@ public class ProjectProductCrudController : BaseController {
2222
};
2323

2424
public ProjectProductCrudController() {
25-
Post("/api/v1/project/product/create", _ => {
25+
Post("/api/v1/project/product/new", _ => {
2626
var projectGuid = GetRequestStr("project_guid");
27-
27+
2828
var me = UserRepository.Find(CurrentRequest.UserId);
2929
var errors = ValidationProcessor.Process(Request, new IValidatorRule[] {
30-
new ShouldHaveParameters(new[] {"project_guid", "name", "description"}),
30+
new ShouldHaveParameters(new[] {"project_guid", "name", "description", "usd_price", "use_url"}),
3131
new ExistsInTable("project_guid", "projects", "guid"),
3232
new HasPermission(me, EntityUtils.GetEntityId(projectGuid, EntityType.Project), EntityType.Project)
3333
});
3434
if (errors.Count > 0) return HttpResponse.Errors(errors);
35+
36+
var price = Convert.ToDecimal(GetRequestStr("usd_price"));
37+
int priceInPennies = (int) (price * 100);
38+
if (priceInPennies < 50) return HttpResponse.Error(
39+
HttpStatusCode.UnprocessableEntity, "Price cannot be less than 0.5 USD"
40+
);
3541

3642
var project = ProjectRepository.FindByGuid(GetRequestStr("project_guid"));
3743

@@ -41,64 +47,61 @@ public ProjectProductCrudController() {
4147
GetRequestStr("url"),
4248
GetRequestStr("use_url")
4349
);
44-
45-
if (!String.IsNullOrEmpty(GetRequestStr("usd_price"))) {
46-
var price = Convert.ToDecimal(GetRequestStr("usd_price"));
47-
int priceInPennies = (int) (price * 100);
48-
49-
product.UpdateCol("usd_price_pennies", priceInPennies);
50-
}
5150

5251
if (!String.IsNullOrEmpty(GetRequestStr("duration_hours"))) {
5352
product.UpdateCol("duration_hours", GetRequestInt("duration_hours"));
5453
}
54+
55+
product.UpdateCol("usd_price_pennies", priceInPennies);
5556

5657
return HttpResponse.Item(
57-
"product", new ProjectProductTransformer().Transform(product.Refresh()), HttpStatusCode.Created
58+
"product", new ProjectProductTransformer().Transform(product.Refresh()),
59+
HttpStatusCode.Created
5860
);
5961
});
6062

61-
Patch("/api/v1/project/product/edit", _ => {
62-
var me = UserRepository.Find(CurrentRequest.UserId);
63-
64-
var product = ProjectProductRepository.FindByGuid(GetRequestStr("product_guid"));
65-
66-
var errors = ValidationProcessor.Process(Request, new IValidatorRule[] {
67-
new ShouldHaveParameters(new[] {"product_guid"}),
68-
new ExistsInTable("product_guid", "project_products", "guid"),
69-
new HasPermission(me, product.project_id, EntityType.Project)
70-
}, true);
71-
if (errors.Count > 0) return HttpResponse.Errors(errors);
72-
73-
if (!String.IsNullOrEmpty(GetRequestStr("name"))) {
74-
product.UpdateCol("name", GetRequestStr("name"));
75-
}
76-
77-
if (!String.IsNullOrEmpty(GetRequestStr("description"))) {
78-
product.UpdateCol("description", GetRequestStr("description"));
79-
}
80-
81-
if (!String.IsNullOrEmpty(GetRequestStr("url"))) {
82-
product.UpdateCol("url", GetRequestStr("url"));
83-
}
84-
85-
if (!String.IsNullOrEmpty(GetRequestStr("set_url"))) {
86-
product.UpdateCol("set_url", GetRequestStr("set_url"));
87-
}
88-
89-
if (!String.IsNullOrEmpty(GetRequestStr("usd_price"))) {
90-
var price = Convert.ToDecimal(GetRequestStr("usd_price"));
91-
int priceInPennies = (int) (price * 100);
92-
93-
product.UpdateCol("usd_price_pennies", priceInPennies);
94-
}
95-
96-
if (!String.IsNullOrEmpty(GetRequestStr("duration_hours"))) {
97-
product.UpdateCol("duration_hours", GetRequestInt("duration_hours"));
98-
}
99-
100-
return HttpResponse.Item("product", new ProjectProductTransformer().Transform(product.Refresh()));
101-
});
63+
// TODO: ???
64+
// Patch("/api/v1/project/product/edit", _ => {
65+
// var me = UserRepository.Find(CurrentRequest.UserId);
66+
//
67+
// var product = ProjectProductRepository.FindByGuid(GetRequestStr("product_guid"));
68+
//
69+
// var errors = ValidationProcessor.Process(Request, new IValidatorRule[] {
70+
// new ShouldHaveParameters(new[] {"product_guid"}),
71+
// new ExistsInTable("product_guid", "project_products", "guid"),
72+
// new HasPermission(me, product.project_id, EntityType.Project)
73+
// }, true);
74+
// if (errors.Count > 0) return HttpResponse.Errors(errors);
75+
//
76+
// if (!String.IsNullOrEmpty(GetRequestStr("name"))) {
77+
// product.UpdateCol("name", GetRequestStr("name"));
78+
// }
79+
//
80+
// if (!String.IsNullOrEmpty(GetRequestStr("description"))) {
81+
// product.UpdateCol("description", GetRequestStr("description"));
82+
// }
83+
//
84+
// if (!String.IsNullOrEmpty(GetRequestStr("url"))) {
85+
// product.UpdateCol("url", GetRequestStr("url"));
86+
// }
87+
//
88+
// if (!String.IsNullOrEmpty(GetRequestStr("set_url"))) {
89+
// product.UpdateCol("set_url", GetRequestStr("set_url"));
90+
// }
91+
//
92+
// if (!String.IsNullOrEmpty(GetRequestStr("usd_price"))) {
93+
// var price = Convert.ToDecimal(GetRequestStr("usd_price"));
94+
// int priceInPennies = (int) (price * 100);
95+
//
96+
// product.UpdateCol("usd_price_pennies", priceInPennies);
97+
// }
98+
//
99+
// if (!String.IsNullOrEmpty(GetRequestStr("duration_hours"))) {
100+
// product.UpdateCol("duration_hours", GetRequestInt("duration_hours"));
101+
// }
102+
//
103+
// return HttpResponse.Item("product", new ProjectProductTransformer().Transform(product.Refresh()));
104+
// });
102105

103106
Delete("/api/v1/project/product/delete", _ => {
104107
var me = UserRepository.Find(CurrentRequest.UserId);
@@ -111,6 +114,9 @@ public ProjectProductCrudController() {
111114
new HasPermission(me, product?.project_id ?? 0, EntityType.Project)
112115
}, true);
113116
if (errors.Count > 0) return HttpResponse.Errors(errors);
117+
118+
if (product != null && product.UsersCount() > 0)
119+
return HttpResponse.Error(HttpStatusCode.Forbidden, "You cannot delete product owned by others");
114120

115121
product?.Delete();
116122

App/AL/Controller/Project/ProjectCrudController.cs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,18 @@ public ProjectCrudController() {
3131
return HttpResponse.Item("project", new ProjectTransformer().Transform(project.Refresh()));
3232
});
3333

34-
Delete("/api/v1/project/delete", _ => {
35-
var errors = ValidationProcessor.Process(Request, new IValidatorRule[] {
36-
new ExistsInTable("project_guid", "projects", "guid"),
37-
});
38-
if (errors.Count > 0) return HttpResponse.Errors(errors);
39-
40-
var project = ProjectRepository.FindByGuid((string) Request.Query["project_guid"]);
41-
ProjectRepository.Delete(project);
42-
43-
return HttpResponse.Item("project", new ProjectTransformer().Transform(project));
44-
});
34+
// TODO: enable?
35+
// Delete("/api/v1/delete", _ => {
36+
// var errors = ValidationProcessor.Process(Request, new IValidatorRule[] {
37+
// new ExistsInTable("project_guid", "projects", "guid"),
38+
// });
39+
// if (errors.Count > 0) return HttpResponse.Errors(errors);
40+
//
41+
// var project = ProjectRepository.FindByGuid((string) Request.Query["project_guid"]);
42+
// ProjectRepository.Delete(project);
43+
//
44+
// return HttpResponse.Item("project", new ProjectTransformer().Transform(project));
45+
// });
4546
}
4647
}
4748
}

App/AL/Controller/UserLibrary/UserLibraryCrudController.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ public UserLibraryCrudController() {
3131
var errors = ValidationProcessor.Process(Request, new IValidatorRule[] {
3232
new ExistsInTable("project_guid", "projects", "guid")
3333
});
34-
if (errors.Count > 0) {
35-
return HttpResponse.Errors(errors);
36-
}
34+
if (errors.Count > 0) return HttpResponse.Errors(errors);
3735

3836
var me = UserRepository.Find(CurrentRequest.UserId);
3937
var project = ProjectRepository.FindByGuid(GetRequestStr("project_guid"));
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using App.DL.Enum;
2+
using App.DL.Repository.User;
3+
using App.DL.Repository.Withdrawal;
4+
using App.PL.Transformer.Withdraw;
5+
using Micron.AL.Validation.Basic;
6+
using Micron.AL.Validation.String;
7+
using Micron.DL.Middleware;
8+
using Micron.DL.Middleware.Auth;
9+
using Micron.DL.Module.Controller;
10+
using Micron.DL.Module.Http;
11+
using Micron.DL.Module.Validator;
12+
using Nancy;
13+
14+
namespace App.AL.Controller.Withdraw {
15+
public class WithdrawalsCrudController : BaseController {
16+
protected override IMiddleware[] Middleware() => new IMiddleware[] { new JwtMiddleware() };
17+
18+
public WithdrawalsCrudController() {
19+
Post("/api/v1/me/withdrawal/new", _ => {
20+
var errors = ValidationProcessor.Process(Request, new IValidatorRule[] {
21+
new ShouldHaveParameters(new[] {"amount", "currency_type", "address"}),
22+
new MinLength("address", 4),
23+
new ShouldBeCorrectEnumValue("currency_type", typeof(CurrencyType)),
24+
}, true);
25+
if (errors.Count > 0) return HttpResponse.Errors(errors);
26+
27+
var me = UserRepository.Find(CurrentRequest.UserId);
28+
29+
var currencyType = (CurrencyType) GetRequestEnum("currency_type", typeof(CurrencyType));
30+
31+
decimal amount = System.Convert.ToDecimal(GetRequestStr("amount"));
32+
33+
if (amount < 0.01M)
34+
return HttpResponse.Error(HttpStatusCode.Forbidden, "Amount cannot be less than 0.01");
35+
36+
var userBalance = UserBalanceRepository.Find(me, currencyType);
37+
if (userBalance == null || amount > userBalance.balance)
38+
return HttpResponse.Error(HttpStatusCode.Forbidden, "You cannot withdraw more that you currently have");
39+
40+
var address = GetRequestStr("address");
41+
42+
var withdrawalRequest = WithdrawalRequestRepository.Create(me, currencyType, amount, address);
43+
44+
return HttpResponse.Item(
45+
"withdraw_request", new WithdrawalRequestTransformer().Transform(withdrawalRequest),
46+
HttpStatusCode.Created
47+
);
48+
});
49+
50+
Get("/api/v1/me/withdrawals/get", _ => {
51+
var me = UserRepository.Find(CurrentRequest.UserId);
52+
var withdrawalRequests = WithdrawalRequestRepository.Get(me);
53+
54+
return HttpResponse.Item(
55+
"withdraw_requests", new WithdrawalRequestTransformer().Many(withdrawalRequests)
56+
);
57+
});
58+
}
59+
}
60+
}

App/DL/Model/Product/ProjectProduct.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public ProjectProduct UpdateCol(string col, int val) {
6969
);
7070
return this;
7171
}
72+
73+
public int UsersCount() => UserOwnedProductRepository.UsersCount(this);
7274

7375
public void Delete() => ExecuteScalarInt("DELETE FROM project_products WHERE id = @id", new {id});
7476

App/DL/Model/Product/UserOwnedProduct.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public static UserOwnedProduct[] GetBy(string col, int val)
3939
=> Connection().Query<UserOwnedProduct>(
4040
$"SELECT * FROM user_owned_products WHERE {col} = @val LIMIT 50", new {val}
4141
).ToArray();
42+
4243

4344
public static int Create(User.User user, ProjectProduct product) {
4445
var expiryAt = DateTime.UtcNow.AddHours(product.duration_hours);
@@ -52,6 +53,13 @@ public static int Create(User.User user, ProjectProduct product) {
5253
);
5354
}
5455

56+
public static int UsersCount(ProjectProduct product)
57+
=> QueryInt(
58+
"SELECT COUNT(*) FROM user_owned_products WHERE product_id = @product_id", new {
59+
product_id = product.id
60+
}
61+
);
62+
5563
public UserOwnedProduct Refresh() => Find(id);
5664

5765
public User.User User() => UserRepository.Find(user_id);

App/DL/Model/User/UserBalance.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ public static UserBalance Find(int id)
3030
"SELECT * FROM user_balances WHERE id = @id LIMIT 1",
3131
new {id}
3232
).FirstOrDefault();
33+
34+
public static UserBalance Find(User user, CurrencyType currencyType)
35+
=> Connection().Query<UserBalance>(
36+
$"SELECT * FROM user_balances WHERE user_id = @user_id AND currency_type = '{currencyType.ToString()}' LIMIT 1",
37+
new {user_id = user.id}
38+
).FirstOrDefault();
3339

3440
public static UserBalance FindByGuid(string guid)
3541
=> Connection().Query<UserBalance>(
@@ -70,7 +76,7 @@ public static UserBalance[] GetPositive(UserModel user, ushort limit = 10)
7076
=> Connection().Query<UserBalance>(
7177
$@"SELECT * FROM user_balances
7278
WHERE user_id = @user_id AND balance > 0
73-
ORDER BY balance DESC LIMIT {limit}"
79+
ORDER BY balance DESC LIMIT {limit}", new {user_id = user.id}
7480
).ToArray();
7581

7682
public UserBalance Refresh() => Find(id);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Linq;
3+
using App.DL.Enum;
4+
using App.DL.Repository.User;
5+
using Dapper;
6+
7+
namespace App.DL.Model.Withdraw {
8+
public class WithdrawalRequest : Micron.DL.Model.Model {
9+
public int id;
10+
11+
public string guid;
12+
13+
public int user_id;
14+
15+
public decimal amount;
16+
17+
public string address;
18+
19+
public bool paid;
20+
21+
public CurrencyType currency_type;
22+
23+
public DateTime created_at;
24+
25+
public static WithdrawalRequest Find(int id)
26+
=> Connection().Query<WithdrawalRequest>(
27+
"SELECT * FROM withdrawal_requests WHERE id = @id LIMIT 1", new {id}
28+
).FirstOrDefault();
29+
30+
public static WithdrawalRequest[] Get(User.User user)
31+
=> Connection().Query<WithdrawalRequest>(
32+
"SELECT * FROM withdrawal_requests WHERE user_id = @user_id LIMIT 100",
33+
new {user_id = user.id}
34+
).ToArray();
35+
36+
public static int Create(User.User user, CurrencyType currencyType, decimal amount, string address) {
37+
return ExecuteScalarInt(
38+
$@"INSERT INTO withdrawal_requests(guid, user_id, currency_type, amount, address)
39+
VALUES (@guid, @user_id, '{currencyType.ToString()}', @amount, @address);
40+
SELECT currval('withdrawal_requests_id_seq');"
41+
, new {
42+
guid = Guid.NewGuid().ToString(), user_id = user.id, amount, address
43+
}
44+
);
45+
}
46+
47+
public User.User User() => UserRepository.Find(user_id);
48+
}
49+
}

App/DL/Repository/Product/UserOwnedProductRepository.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@ public static class UserOwnedProductRepository {
1515
public static UserOwnedProduct Create(Model.User.User user, ProjectProduct product) {
1616
return Find(UserOwnedProduct.Create(user, product));
1717
}
18+
19+
public static int UsersCount(ProjectProduct product) => UserOwnedProduct.UsersCount(product);
1820
}
1921
}

0 commit comments

Comments
 (0)