Во дела, в нормальной обстановке, без спешки сделал тест по вакансии как белый человек. Вчера на этот тест после 37 теоретических вопросов оставалось всего 30 минут. Это не дело.
В таком состоянии отослал:
Сегодня всё по красоте:
BankController.cs
using InternetBankingRESTfulService.Api;
using InternetBankingRESTfulService.Api.Core;
using Microsoft.AspNetCore.Mvc;
namespace InternetBankingRESTfulService.Web.Controllers
{
[ApiController]
[Route("[controller]")]
public class BankController : ControllerBase
{
private InternetBankingApi BankingApi { get; }
public BankController()
{
BankingApi = new InternetBankingApi();
}
[HttpGet("api/version")]
public IActionResult GetApiVersion()
{
return Ok(BankingApi.GetApiVersion());
}
[HttpGet("api-version")]
public IActionResult GetApiVersionSecond()
{
return Ok(BankingApi.GetApiVersion());
}
[HttpGet("api/calc/MD5/{value}")]
public IActionResult CalculateMD5(string value)
{
return Ok(BankingApi.CalculateMD5(Helper.ReplaceDigitsByString(value)));
}
[HttpGet("api/calc/{value}/MD5")]
public IActionResult CalculateMD5Second(string value)
{
return Ok(BankingApi.CalculateMD5(Helper.ReplaceDigitsByString(value)));
}
[HttpGet("api/password/strong/{value}")]
public IActionResult PasswordStrong(string value)
{
return Ok(BankingApi.IsPasswordStrong(value));
}
[HttpGet("api/is-password-strong/{value}")]
public IActionResult IsPasswordStrong(string value)
{
return Ok(BankingApi.IsPasswordStrong(value));
}
}
}
InternetBankingApi.cs
using InternetBankingRESTfulService.Api.Core;
using System;
namespace InternetBankingRESTfulService.Api
{
public class InternetBankingApi : IInternetBankingApi
{
private readonly string _apiVersion = $"{DateTime.UtcNow:yyyy.MM.dd}.1.0";
public string GetApiVersion()
{
return _apiVersion;
}
public string CalculateMD5(string value)
{
return Security.MD5Encode(value);
}
public bool IsPasswordStrong(string password)
{
return Security.IsPasswordStrong(password);
}
}
}
Security.cs
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Text;
using System;
using System.Linq;
namespace InternetBankingRESTfulService.Api.Core
{
public static class Security
{
/// <summary>
/// Returns MD5 hash string.
/// </summary>
/// <param name="plainText"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static string MD5Encode(string plainText)
{
if (string.IsNullOrEmpty(plainText))
throw new ArgumentException("Text cannot be empty.");
return string.Concat(MD5.HashData(Encoding.UTF8.GetBytes(plainText)).Select(x => x.ToString("x2"))).ToUpper();
}
/// <summary>
/// Validate password strength.
/// </summary>
/// <param name="plainPassword"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static bool IsPasswordStrong(string plainPassword)
{
if (string.IsNullOrEmpty(plainPassword))
throw new ArgumentException("Password cannot be empty.");
return new Regex(@"(?=^.{12,}$)(?=.*\d)(?=.*[!@#$%^&*]+)(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$").IsMatch(plainPassword);
}
}
}
Helper.cs
using System.Text.RegularExpressions;
namespace InternetBankingRESTfulService.Api.Core
{
public static class Helper
{
/// <summary>
/// Replace all digits in value parameter by char.
/// </summary>
/// <param name="value"></param>
/// <param name="replaceNumberBy">Default char value is 'X'.</param>
/// <returns></returns>
public static string ReplaceDigitsByString(string value, string replaceDigitBy = "X")
{
return Regex.Replace(value, @"\d", replaceDigitBy);
}
}
}
ApiTest.cs
using Microsoft.AspNetCore.Mvc.Testing;
using NUnit.Framework;
using System;
using System.Globalization;
using System.Threading.Tasks;
namespace InternetBankingRESTfulService.Tests
{
public class ApiTest
{
[Test]
public async Task TestApiVersion()
{
var factory = new WebApplicationFactory<Startup>();
var Client = factory.CreateClient();
var result = await Client.GetAsync("/bank/api/version");
Assert.AreEqual(System.Net.HttpStatusCode.OK, result.StatusCode);
var content = result.Content;
var data = await content.ReadAsStringAsync();
Assert.AreEqual($"{DateTime.UtcNow.ToString("yyyy.MM.dd", CultureInfo.InvariantCulture)}.1.0", data);
}
[Test]
public async Task TestApiVersion_Second()
{
var factory = new WebApplicationFactory<Startup>();
var Client = factory.CreateClient();
var result = await Client.GetAsync("/bank/api-version");
Assert.AreEqual(System.Net.HttpStatusCode.OK, result.StatusCode);
var content = result.Content;
var data = await content.ReadAsStringAsync();
Assert.AreEqual($"{DateTime.UtcNow.ToString("yyyy.MM.dd", CultureInfo.InvariantCulture)}.1.0", data);
}
[Test]
public async Task TestPasswordStrongIsFalse()
{
var factory = new WebApplicationFactory<Startup>();
var Client = factory.CreateClient();
var result = await Client.GetAsync($"/bank/api/password/strong/123");
Assert.AreEqual(System.Net.HttpStatusCode.OK, result.StatusCode);
var content = result.Content;
var data = await content.ReadAsStringAsync();
Assert.AreEqual("false", data);
}
[Test]
public async Task TestPasswordStrongIsTrue()
{
var factory = new WebApplicationFactory<Startup>();
var Client = factory.CreateClient();
var result = await Client.GetAsync($"/bank/api/password/strong/ALhj89*19896");
Assert.AreEqual(System.Net.HttpStatusCode.OK, result.StatusCode);
var content = result.Content;
var data = await content.ReadAsStringAsync();
Assert.AreEqual("true", data);
}
[Test]
public async Task CalculateMD5()
{
var factory = new WebApplicationFactory<Startup>();
var Client = factory.CreateClient();
var result = await Client.GetAsync($"/bank/api/calc/MD5/test-string-ABC");
Assert.AreEqual(System.Net.HttpStatusCode.OK, result.StatusCode);
var content = result.Content;
var data = await content.ReadAsStringAsync();
Assert.AreEqual("79C8DC4F3BAEBF0A4F40517225F41A86", data);
}
[Test]
public async Task CalculateMD5_SecondURL()
{
var factory = new WebApplicationFactory<Startup>();
var Client = factory.CreateClient();
var result = await Client.GetAsync($"/bank/api/calc/test-string-ABC/MD5");
Assert.AreEqual(System.Net.HttpStatusCode.OK, result.StatusCode);
var content = result.Content;
var data = await content.ReadAsStringAsync();
Assert.AreEqual("79C8DC4F3BAEBF0A4F40517225F41A86", data);
}
}
}