Skip to content

Commit

Permalink
Refactoring: Added random character generator and string shuffler ser…
Browse files Browse the repository at this point in the history
…vice
  • Loading branch information
djvelimir committed Oct 28, 2022
1 parent b86401a commit 32e9524
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 57 deletions.
4 changes: 2 additions & 2 deletions Controllers/PasswordController.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using demo_dotnet_web_api.Interfaces;
using DemoDotnetWebApi.Interfaces;
using Microsoft.AspNetCore.Mvc;

namespace demo_dotnet_web_api.Controllers;
namespace DemoDotnetWebApi.Controllers;

[ApiController]
[Route("api/v1/[controller]")]
Expand Down
4 changes: 2 additions & 2 deletions Interfaces/IPasswordGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace demo_dotnet_web_api.Interfaces;
namespace DemoDotnetWebApi.Interfaces;

public interface IPasswordGenerator
{
String Generate();
}
}
14 changes: 14 additions & 0 deletions Interfaces/IRandomCharacterGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace DemoDotnetWebApi.Interfaces;

public interface IRandomCharacterGenerator
{
char GenerateUppercaseCharacter();

char GenerateLowercaseCharacter();

char GenerateDigitCharacter();

char GenerateSpecialCharacter();

char GenerateAllowedCharacter();
}
6 changes: 6 additions & 0 deletions Interfaces/IStringShuffler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace DemoDotnetWebApi.Interfaces;

public interface IStringShuffler
{
string Shuffle(string characters);
}
8 changes: 5 additions & 3 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using demo_dotnet_web_api.Interfaces;
using demo_dotnet_web_api.Services;
using DemoDotnetWebApi.Interfaces;
using DemoDotnetWebApi.Services;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddSingleton<IPasswordGenerator, PasswordGenerator>();
builder.Services.AddTransient<IPasswordGenerator, PasswordGenerator>();
builder.Services.AddTransient<IRandomCharacterGenerator, RandomCharacterGenerator>();
builder.Services.AddTransient<IStringShuffler, StringShuffler>();

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
Expand Down
2 changes: 1 addition & 1 deletion Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
}
},
"profiles": {
"demo_dotnet_web_api": {
"DemoDotnetWebApi": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
Expand Down
76 changes: 29 additions & 47 deletions Services/PasswordGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,62 +1,44 @@
using System.Text;
using demo_dotnet_web_api.Interfaces;
using DemoDotnetWebApi.Interfaces;

namespace demo_dotnet_web_api.Services;
namespace DemoDotnetWebApi.Services;

public class PasswordGenerator : IPasswordGenerator
{
private static readonly int PASSWORD_LENGTH = 16;
private static readonly String UPPERCASE_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static readonly String LOWERCASE_CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
private static readonly String DIGIT_CHARACTERS = "0123456789";
private static readonly String SPECIAL_CHARACTERS = "~`!@#$%^&*()-_=+[{]}\\|;:\'\",<.>/?";
private static readonly String UNION_OF_ALLOWED_CHARACTERS = UPPERCASE_CHARACTERS +
LOWERCASE_CHARACTERS +
DIGIT_CHARACTERS +
SPECIAL_CHARACTERS;
private static readonly Random random = new Random();
private readonly int passwordLength;
private readonly IRandomCharacterGenerator randomCharacterGenerator;
private readonly IStringShuffler stringShuffler;

/// <summary>
/// Generate random password
/// Generated password length is 16
/// Generated password contains at least one uppercase character
/// Generated password contains at least one lowercase character
/// Generated password contains at least one digit character
/// Generated password contains at least one special character
/// </summary>
/// <returns>Generated password</returns>
public PasswordGenerator(IRandomCharacterGenerator randomCharacterGenerator, IStringShuffler stringShuffler)
{
this.passwordLength = 16;
this.randomCharacterGenerator = randomCharacterGenerator;
this.stringShuffler = stringShuffler;
}

/// <summary>
/// Generate random password
/// Generated password length is 16
/// Generated password contains at least one uppercase character
/// Generated password contains at least one lowercase character
/// Generated password contains at least one digit character
/// Generated password contains at least one special character
/// </summary>
/// <returns>Generated password</returns>
public String Generate()
{
var stringBuilder = new StringBuilder();

// generate at least one uppercase character
stringBuilder.Append(GenerateRandomCharacter(UPPERCASE_CHARACTERS));

// generate at least one lowercase character
stringBuilder.Append(GenerateRandomCharacter(LOWERCASE_CHARACTERS));

// generate at least one digit character
stringBuilder.Append(GenerateRandomCharacter(DIGIT_CHARACTERS));
stringBuilder.Append(randomCharacterGenerator.GenerateUppercaseCharacter());
stringBuilder.Append(randomCharacterGenerator.GenerateLowercaseCharacter());
stringBuilder.Append(randomCharacterGenerator.GenerateDigitCharacter());
stringBuilder.Append(randomCharacterGenerator.GenerateSpecialCharacter());

// generate at least one special character
stringBuilder.Append(GenerateRandomCharacter(SPECIAL_CHARACTERS));

for (int i = 4; i < PASSWORD_LENGTH; i++)
for (int i = 0; i < passwordLength - 4; i++)
{
// generate random character from union of allowed characters
stringBuilder.Append(GenerateRandomCharacter(UNION_OF_ALLOWED_CHARACTERS));
stringBuilder.Append(randomCharacterGenerator.GenerateAllowedCharacter());
}

// shuffle generated characters
IList<String> ch = stringBuilder.ToString().Split("").ToList();
ch.Shuffle();

// return generated password
return string.Join("", ch);
}

private char GenerateRandomCharacter(String characters)
{
return characters.ElementAt(random.Next(characters.Length));
return stringShuffler.Shuffle(stringBuilder.ToString());
}
}
}
50 changes: 50 additions & 0 deletions Services/RandomCharacterGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using DemoDotnetWebApi.Interfaces;

namespace DemoDotnetWebApi.Services;

public class RandomCharacterGenerator : IRandomCharacterGenerator
{
private readonly String uppercaseCharacters;
private readonly String lowercaseCharacters;
private readonly String digitCharacters;
private readonly String specialCharacters;
private readonly String allowedCharacters;
private readonly Random random = new Random();

public RandomCharacterGenerator()
{
uppercaseCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
lowercaseCharacters = "abcdefghijklmnopqrstuvwxyz";
digitCharacters = "0123456789";
specialCharacters = "~`!@#$%^&*()-_=+[{]}\\|;:\'\",<.>/?";
allowedCharacters = uppercaseCharacters +
lowercaseCharacters +
digitCharacters +
specialCharacters;
}

public char GenerateAllowedCharacter()
{
return allowedCharacters.ElementAt(random.Next(allowedCharacters.Length));
}

public char GenerateDigitCharacter()
{
return digitCharacters.ElementAt(random.Next(digitCharacters.Length));
}

public char GenerateLowercaseCharacter()
{
return lowercaseCharacters.ElementAt(random.Next(lowercaseCharacters.Length));
}

public char GenerateSpecialCharacter()
{
return specialCharacters.ElementAt(random.Next(specialCharacters.Length));
}

public char GenerateUppercaseCharacter()
{
return uppercaseCharacters.ElementAt(random.Next(uppercaseCharacters.Length));
}
}
25 changes: 25 additions & 0 deletions Services/StringShuffler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using DemoDotnetWebApi.Interfaces;

namespace DemoDotnetWebApi.Services;

public class StringShuffler : IStringShuffler
{
private readonly Random random = new Random();

public string Shuffle(string characters)
{
IList<string> list = characters.Split("").ToList();
int n = list.Count;

while (n > 1)
{
n--;
int k = random.Next(n + 1);
string value = list[k];
list[k] = list[n];
list[n] = value;
}

return string.Join("", list);
}
}
2 changes: 1 addition & 1 deletion ShuffleExtension.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace demo_dotnet_web_api;
namespace DemoDotnetWebApi;

public static class ShuffleExtension
{
Expand Down
2 changes: 1 addition & 1 deletion demo-dotnet-web-api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>demo_dotnet_web_api</RootNamespace>
<RootNamespace>DemoDotnetWebApi</RootNamespace>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit 32e9524

Please sign in to comment.