Skip to content

Commit

Permalink
Policies
Browse files Browse the repository at this point in the history
  • Loading branch information
GrantErickson committed May 23, 2024
1 parent 9199aa5 commit 91c2420
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Wordle.Api/Wordle.Api/Controllers/TokenController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public async Task<IActionResult> GetToken([FromBody] UserCredentialsDto userCred
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new("userId", user.Id.ToString()),
new("userName", user.UserName!.ToString().Substring(0,user.UserName.ToString().IndexOf("@"))), // Use the email as the username, but get rid of the email domain
new("MyThing", "Thing"),
new(Claims.Random, (new Random()).NextDouble().ToString())
};

// Retrieve all roles associated with the user
Expand Down
14 changes: 12 additions & 2 deletions Wordle.Api/Wordle.Api/Controllers/WordController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Wordle.Api.Identity;
using Wordle.Api.Services;

namespace Wordle.Api.Controllers;
Expand All @@ -26,13 +27,22 @@ public async Task<string> GetWordOfDay(double offsetInHours = -7.0)
return await wordOfTheDayService.GetWordOfTheDay(today);
}

[Authorize]
[Authorize(Roles = Roles.Admin)]
[HttpGet("WordOfTheDayHint")]
public async Task<string> GetWordOfDayHint(double offsetInHours = -7.0)
{
DateOnly today = DateOnly.FromDateTime(DateTime.UtcNow.AddHours(offsetInHours));
var wordOfTheDay = await wordOfTheDayService.GetWordOfTheDay(today);

return wordOfTheDay.Substring(0, 1) + "___" + wordOfTheDay.Substring(4,1);
return wordOfTheDay.Substring(0, 1) + "___" + wordOfTheDay.Substring(4, 1);
}

[HttpGet("SecuredRandomWord")]
[Authorize(Policy = Policies.RandomAdmin)]
public async Task<string> GetSecuredRandomWord()
{
var randomWord = await wordOfTheDayService.GetRandomWord("sec");
return randomWord.Text;
}

}
8 changes: 8 additions & 0 deletions Wordle.Api/Wordle.Api/Identity/Claims.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Wordle.Api.Identity;

public static class Claims
{
public const string Random = "Random";
public const string BirthDate = "BirthDate";
}

21 changes: 21 additions & 0 deletions Wordle.Api/Wordle.Api/Identity/IdentitySeed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ private static async Task SeedRolesAsync(RoleManager<IdentityRole> roleManager)
{
await roleManager.CreateAsync(new IdentityRole(Roles.Admin));
}
// Seed Roles
if (!await roleManager.RoleExistsAsync(Roles.Awesome))
{
await roleManager.CreateAsync(new IdentityRole(Roles.Awesome));
}
}

private static async Task SeedAdminUserAsync(UserManager<AppUser> userManager)
Expand All @@ -43,5 +48,21 @@ private static async Task SeedAdminUserAsync(UserManager<AppUser> userManager)
await userManager.AddToRoleAsync(user, Roles.Admin);
}
}

if (await userManager.FindByEmailAsync("[email protected]") == null)
{
AppUser user = new AppUser
{
UserName = "[email protected]",
Email = "[email protected]"
};

IdentityResult result = userManager.CreateAsync(user, "P@ssw0rd123").Result;

if (result.Succeeded)
{
await userManager.AddToRoleAsync(user, Roles.Awesome);
}
}
}
}
24 changes: 24 additions & 0 deletions Wordle.Api/Wordle.Api/Identity/Policies.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using System.ComponentModel;

namespace Wordle.Api.Identity;
public static class Policies
{
public const string RandomAdmin = "RandomAdmin";

public static void RandomAdminPolicy(AuthorizationPolicyBuilder policy)
{
policy.RequireRole(Roles.Admin);
policy.RequireAssertion(context =>
{
var random = context.User.Claims.FirstOrDefault(c => c.Type == Claims.Random);
if (Double.TryParse(random?.Value, out double result))
{
return result > 0.5;
}
return false;
});
}

}
1 change: 1 addition & 0 deletions Wordle.Api/Wordle.Api/Identity/Roles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
public static class Roles
{
public const string Admin = "Admin";
public const string Awesome = "Awesome";
}
2 changes: 2 additions & 0 deletions Wordle.Api/Wordle.Api/Models/Word.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.ComponentModel.DataAnnotations;

namespace Wordle.Api.Models;


public class Word
{
public int WordId { get; set; }
Expand Down
40 changes: 39 additions & 1 deletion Wordle.Api/Wordle.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System;
using System.Text;
using Wordle.Api;
Expand Down Expand Up @@ -32,7 +33,33 @@
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSwaggerGen(config =>
{
config.SwaggerDoc("v1", new OpenApiInfo { Title = "Wordle API", Version = "v1" });
config.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = "Bearer"
});
config.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new List<string>()
}
});
}
);

builder.Services.AddScoped<WordOfTheDayService>();
builder.Services.AddScoped<GameService>();
Expand Down Expand Up @@ -62,6 +89,17 @@
}
);

//Add Policies
builder.Services.AddAuthorization(options =>
{
options.AddPolicy(Policies.RandomAdmin, Policies.RandomAdminPolicy);
//options.AddPolicy("IsGrantPolicy", policy => policy.RequireRole("Grant"));
//options.AddPolicy(Policies.EditWord, Policies.EditWordPolicy);
});




var app = builder.Build();

using (var scope = app.Services.CreateScope())
Expand Down
9 changes: 6 additions & 3 deletions Wordle.Api/Wordle.Api/Services/WordOfTheDayService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ public WordOfTheDayService(WordleDbContext db)
Db = db;
}

public async Task<Word> GetRandomWord()
public async Task<Word> GetRandomWord(string containtsText = "")
{
var numberOfWords = await Db.Words.CountAsync();
var numberOfWords = await Db.Words.CountAsync(f=>f.Text.Contains(containtsText));

Random random = new();
int randomIndex = random.Next(numberOfWords);

return await Db.Words.Skip(randomIndex).FirstAsync();
return await Db.Words
.Where(f=>f.Text.Contains(containtsText))
.Skip(randomIndex)
.FirstAsync();
}

public async Task<string> GetWordOfTheDay(DateOnly date)
Expand Down

0 comments on commit 91c2420

Please sign in to comment.