Skip to content

Commit 2ab56c9

Browse files
Merge pull request #88 from pappyangel/SQLInjection
Fix Sql injection issues and add env display
2 parents c27416b + 7c3c22c commit 2ab56c9

12 files changed

+115
-31
lines changed

.vscode/launch.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"request": "launch",
3232
"preLaunchTask": "build API",
3333
// If you have changed target frameworks, make sure to update the program path.
34-
"program": "${workspaceFolder}/cocktails/bin/Debug/net7.0/cocktails.dll",
34+
"program": "${workspaceFolder}/cocktails/bin/Debug/net8.0/cocktails.dll",
3535
"args": [],
3636
"cwd": "${workspaceFolder}/cocktails",
3737
"stopAtEntry": false,

cocktails/Controllers/CocktailController.cs

+7-3
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,13 @@ public async Task<ActionResult<string>> UpdateCocktail(Item item)
166166
}
167167

168168
// cocktail/Post -- Delete Item
169-
[HttpDelete("id/{id:int}")]
169+
170170
//[HttpDelete]
171-
public async Task<ActionResult<string>> DeleteCocktail(int id)
171+
//public async Task<ActionResult<string>> DeleteCocktail(Item item)
172+
173+
[HttpDelete("id/{id:int}")]
174+
public async Task<ActionResult<string>> DeleteCocktail(int id)
175+
172176
{
173177
int rowsAffected;
174178

@@ -182,7 +186,7 @@ public async Task<ActionResult<string>> DeleteCocktail(int id)
182186
return NotFound();
183187

184188

185-
_logger.LogInformation("Received request to delete by this item id: {@int}", id);
189+
_logger.LogInformation("Received request to delete this item: {@int}", id);
186190

187191
return $"Row(s) deleted were: {rowsAffected}";
188192

cocktails/DB/SqlDb.cs

+65-12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Threading.Tasks;
66
using cocktails.models;
77
using Microsoft.Extensions.Configuration;
8+
using System;
89

910
namespace cocktails.DB
1011
{
@@ -30,12 +31,19 @@ public SqlDb(IConfiguration configuration)
3031

3132
public SqlConnection GetSQLCn()
3233
{
34+
var env = _configuration["ASPNETCORE_ENVIRONMENT"];
35+
bool isDevelopment = env == "Development";
36+
3337
var builder = new SqlConnectionStringBuilder(
3438
_configuration["ConnectionStrings:defaultConnection"]);
39+
40+
if (isDevelopment)
41+
{
42+
// The below 2 lines are used during development only. SMI is used in Production
43+
var keyVaultSecretLookup = _configuration["AzureKeyVaultSecret:defaultSecret"];
44+
builder.Password = _configuration.GetValue<string>(keyVaultSecretLookup);
45+
}
3546

36-
// The below 2 lines are used during development only. SMI is used in Production
37-
var keyVaultSecretLookup = _configuration["AzureKeyVaultSecret:defaultSecret"];
38-
// builder.Password = _configuration.GetValue<string>(keyVaultSecretLookup);
3947

4048
SqlConnection sqlDBCn = new SqlConnection(builder.ConnectionString);
4149

@@ -161,7 +169,50 @@ private int CRUD(string sqlStatetment)
161169
return rowsAffected;
162170

163171
}
164-
private async Task<int> CRUDAsync(string sqlStatetment)
172+
private async Task<int> CRUDAsync(string sqlStatetment, Item item)
173+
{
174+
int rowsAffected = 0;
175+
176+
using SqlConnection SQLCn = GetSQLCn();
177+
178+
using SqlCommand crudCommand = new SqlCommand(sqlStatetment, SQLCn);
179+
crudCommand.CommandType = CommandType.Text;
180+
181+
bool IgnoreCase = true;
182+
if (sqlStatetment.StartsWith("D", IgnoreCase, null) | sqlStatetment.StartsWith("U", IgnoreCase, null))
183+
crudCommand.Parameters.Add("@ItemId", SqlDbType.Int).Value = item.Id;
184+
185+
if (sqlStatetment.StartsWith("I", IgnoreCase, null) | sqlStatetment.StartsWith("U", IgnoreCase, null))
186+
{
187+
crudCommand.Parameters.Add("@ItemName", SqlDbType.VarChar, 50).Value = item.Name;
188+
var paramPrice = crudCommand.Parameters.Add("@ItemPrice", SqlDbType.Decimal);
189+
paramPrice.Value = item.Price;
190+
paramPrice.Precision = 10;
191+
paramPrice.Scale = 2;
192+
var paramRating = crudCommand.Parameters.Add("@ItemRating", SqlDbType.Decimal);
193+
paramRating.Value = item.Rating;
194+
paramRating.Precision = 10;
195+
paramRating.Scale = 2;
196+
crudCommand.Parameters.Add("@ItemImagePath", SqlDbType.VarChar, 255).Value = item.ImagePath;
197+
}
198+
199+
try
200+
{
201+
await SQLCn.OpenAsync();
202+
rowsAffected = await crudCommand.ExecuteNonQueryAsync();
203+
}
204+
catch (Exception Ex)
205+
{
206+
string methodReturnValue = Ex.Message;
207+
rowsAffected = -1;
208+
// throw;
209+
}
210+
211+
return rowsAffected;
212+
213+
}
214+
215+
private async Task<int> oldCRUDAsync(string sqlStatetment)
165216
{
166217
SqlCommand command;
167218
int rowsAffected;
@@ -182,29 +233,31 @@ private async Task<int> CRUDAsync(string sqlStatetment)
182233
public async Task<int> DeleteItembyId(int id)
183234
{
184235
int crudResult;
185-
string sql = $"Delete from {tblName} where Id = {id}";
236+
Item itemToDelete = new Item { Id = id };
186237

187-
crudResult = await CRUDAsync(sql);
238+
string sql = $"Delete from {tblName} where Id = @ItemId";
239+
240+
crudResult = await CRUDAsync(sql, itemToDelete);
188241

189242
return crudResult;
190243
}
191244

192245
public async Task<int> UpdateItembyId(Item item)
193246
{
194247
int crudResult;
195-
string sql = $"Update t Set t.name = '{item.Name}', t.price = {item.Price}, t.rating = {item.Rating}, t.ImagePath = '{item.ImagePath}'"
196-
+ $" From {tblName} t where t.id = {item.Id}";
248+
string sql = $"Update t Set t.name = @ItemName, t.price = @ItemPrice, t.rating = @ItemRating, t.ImagePath = @ItemImagePath"
249+
+ $" From {tblName} t where t.id = @ItemId";
197250

198-
crudResult = await CRUDAsync(sql);
251+
crudResult = await CRUDAsync(sql,item);
199252

200253
return crudResult;
201254
}
202255
public async Task<int> InsertItem(Item item)
203256
{
204257
int crudResult;
205-
string sql = $"Insert into {tblName} (Name, Price ,Rating) values ('{item.Name}', {item.Price}, {item.Rating})";
206-
207-
crudResult = await CRUDAsync(sql);
258+
string sql = $"Insert into {tblName} (Name, Price ,Rating, ImagePath) values (@ItemName, @ItemPrice, @ItemRating, @ItemImagePath)";
259+
item.ImagePath = item.ImagePath ?? "NoImageSelected.png";
260+
crudResult = await CRUDAsync(sql, item);
208261

209262
return crudResult;
210263
}

cocktails/Data/Create and Populate Item for Cocktail.sql

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ GO
55
-- Create the table in the specified schema
66
CREATE TABLE [dbo].[Items] (
77
[Id] INT IDENTITY (1001, 1) NOT NULL,
8-
[Name] VARCHAR (20) NULL,
8+
[Name] VARCHAR (50) NULL,
99
[Price] NUMERIC (10, 2) NULL,
1010
[Rating] NUMERIC (10, 2) NULL,
11-
[ImagePath] VARCHAR (255) CONSTRAINT [DEFAULT_Items_ImagePath] DEFAULT ('NoImage.jpg') NULL,
11+
[ImagePath] VARCHAR (255) CONSTRAINT [DEFAULT_Items_ImagePath] DEFAULT ('NoImageSelected.png') NULL,
1212
PRIMARY KEY CLUSTERED ([Id] ASC)
1313
);
1414
GO

cocktails/Properties/launchSettings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
},
2020
"cocktails": {
2121
"commandName": "Project",
22-
"dotnetRunMessages": "true",
22+
"dotnetRunMessages": true,
2323
"launchBrowser": true,
2424
"launchUrl": "swagger",
2525
"applicationUrl": "https://localhost:5001;http://localhost:5000",

cocktails/appsettings.Development.json

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,17 @@
66
"Microsoft.Hosting.Lifetime": "Information"
77
}
88
},
9-
"AllowedHosts": "*"
9+
"AllowedHosts": "*",
10+
"AzureServicesAuthConnectionString": "RunAs=Developer;DeveloperTool=AzureCli;",
11+
"ManagedIdentity-AzureServicesAuthConnectionString": "RunAs=App",
12+
"LocalDev-AzureServicesAuthConnectionString": "RunAs=Developer;DeveloperTool=AzureCli;",
13+
"ConnectionStrings": {
14+
"defaultConnection": "Server=tcp:jfv-sql.database.windows.net,1433;Initial Catalog=dbItems;Persist Security Info=False;User ID=dbadmin;Password=;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30",
15+
"ProductionConnection-ManagedIdentity": "Server=tcp:jfv-sql.database.windows.net;Authentication=Active Directory Default; Database=dbItems;",
16+
"DevelopmentConnection-SQLAuth": "Server=tcp:jfv-sql.database.windows.net,1433;Initial Catalog=dbItems;Persist Security Info=False;User ID=dbadmin;Password=;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30",
17+
"MCAPSOld-defaultConnection": "Server=tcp:sql-jfv.database.windows.net;Authentication=Active Directory Default; Database=SocialEvents;",
18+
"MCAPSOld-defaultSQLAuthConnection": "Server=tcp:sql-jfv.database.windows.net,1433;Initial Catalog=SocialEvents;Persist Security Info=False;User ID=dbadmin;Password=;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30"
19+
}
1020

1121

1222

frontend/Models/APICocktailRepository.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,17 @@ public async Task<List<Item>> AddItemAsync(Item cocktailToAdd)
8080
return cocktailList;
8181
}
8282

83-
public async Task<List<Item>> DeleteItemAsync(int cocktailIdToDelete)
83+
//public async Task<List<Item>> DeleteItemAsync(int cocktailIdToDelete)
84+
public async Task<List<Item>> DeleteItemAsync(Item cocktailToDelete)
8485
{
8586

86-
var deleteUrl = apiUrl + "/id/" + cocktailIdToDelete;
87+
var deleteUrl = apiUrl + "/id/" + cocktailToDelete.Id;
8788
var response = await APIclient.DeleteAsync(deleteUrl);
8889

90+
// var jsonItem = JsonSerializer.Serialize(cocktailIdToDelete);
91+
// var httpContent = new StringContent(jsonItem, Encoding.UTF8, "application/json");
92+
// var response = await APIclient.DeleteAsync(apiUrl, httpContent)
93+
8994

9095
cocktailList = await APIclient.GetFromJsonAsync<List<Item>>(apiUrl);
9196

frontend/Models/ICocktailRepository.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public interface ICocktailRepository
1515
Task<List<Item>> UpdateItemAsync(Item updatedItem);
1616

1717
Task<List<Item>> AddItemAsync(Item cocktailToAdd);
18-
Task<List<Item>> DeleteItemAsync(int cocktailIdToDelete);
18+
Task<List<Item>> DeleteItemAsync(Item cocktailToDelete);
1919

2020
}
2121

frontend/Pages/DeleteCocktail.cshtml.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ public IActionResult OnGet(int id)
3232
public async Task<IActionResult> OnPost(Item cocktailToDelete)
3333
{
3434
// call the add method
35-
await cocktailRepository.DeleteItemAsync(cocktailToDelete.Id);
36-
35+
//await cocktailRepository.DeleteItemAsync(cocktailToDelete.Id);
36+
await cocktailRepository.DeleteItemAsync(cocktailToDelete);
37+
3738
// redirect to summary page
3839
return Redirect("/Cocktails");
3940

frontend/Pages/Index.cshtml

+7
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,10 @@
1010
<p>July 2024</p>
1111
<p><a href="https://cocktail-api.azurewebsites.net/cocktails">Hit the API directly!</a></p>
1212
</div>
13+
14+
<environment include="Development">
15+
<div>Environment is Development</div>
16+
</environment>
17+
<environment exclude="Development">
18+
<div>Environment is NOT Development</div>
19+
</environment>

frontend/Properties/launchSettings.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
},
1818
"frontend": {
1919
"commandName": "Project",
20-
"dotnetRunMessages": "true",
20+
"dotnetRunMessages": true,
2121
"launchBrowser": true,
22-
"applicationUrl": "https://localhost:5001;http://localhost:5000",
22+
"applicationUrl": "https://localhost:3001;http://localhost:3000",
2323
"environmentVariables": {
2424
"ASPNETCORE_ENVIRONMENT": "Development"
2525
}

frontend/appsettings.Development.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
"DetailedErrors": true,
33
"Logging": {
44
"LogLevel": {
5-
"Default": "Information",
6-
"Microsoft": "Warning",
7-
"Microsoft.Hosting.Lifetime": "Information"
5+
"Default": "Information",
6+
"Microsoft": "Warning",
7+
"Microsoft.Hosting.Lifetime": "Information"
88
}
9-
}
9+
},
10+
"AllowedHosts": "*",
11+
"APIProductionUrl": "http://127.0.0.1:5000/cocktails",
12+
"FY25-APIProductionUrl": "https://cocktail-api.azurewebsites.net/cocktails",
13+
"Dev-APIUrl": "http://127.0.0.1:5000/cocktails"
1014
}

0 commit comments

Comments
 (0)