https://github.com/oznakdn/GraphQL-Learning
https://github.com/oznakdn/GraphQL-Learning
bogus efcore grapql grapql-server hot-chocolate jwt-authentication jwt-authorization
Last synced: 3 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/oznakdn/GraphQL-Learning
- Owner: oznakdn
- Created: 2024-02-16T08:12:14.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2024-03-07T13:54:25.000Z (over 1 year ago)
- Last Synced: 2025-06-15T06:47:56.850Z (4 months ago)
- Topics: bogus, efcore, grapql, grapql-server, hot-chocolate, jwt-authentication, jwt-authorization
- Language: C#
- Homepage:
- Size: 23.4 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
![]()
Hot Chocolate documentation
Examples documentation
Example documentation# Nuget Package
```csharp
HotChocolate.AspNetCore
HotChocolate.AspNetCore.Authorization
Microsoft.AspNetCore.Authentication.JwtBearer
HotChocolate.Data.EntityFramework
Microsoft.EntityFrameworkCore.InMemory
```# Program.cs
```csharp
builder.Services.AddScoped();
builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("ApiDb"));
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "http://localhost:5054",
ValidAudience = "http://localhost:5054",
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("c082a53a-938b-4504-8cff-def4667e8854"))
};
});builder.Services.AddAuthorization(options =>
{
options.AddPolicy("HasRole", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c => c.Type == ClaimTypes.Role)));
});builder.Services.AddGraphQLServer()
.AddAuthorization()
.AddProjections()
.AddFiltering()
.AddSorting()
.AddQueryType()
.AddMutationType()
.AddSubscriptionType();var app = builder.Build();
app.SeedData();
app.UseAuthentication();
app.UseAuthorization();
app.UseWebSockets();
app.MapGraphQL();
app.Run();
```# Models
```csharp
public class Project
{
public string Id { get; set; }
public string Name { get; set; }public ICollection Members { get; set; } = new HashSet();
}
``````csharp
public class Member
{
public string Id { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
public string Title { get; set; }public string ProjectId { get; set; }
public Project? Project { get; set; }
}
``````csharp
public class User
{
public string Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string Username { get; set; }public string? RoleId { get; set; }
public Role? Role { get; set; }}
``````csharp
public class Role
{
public string Id { get; set; }
public string Name { get; set; }public ICollection Users { get; set; } = new HashSet();
}
```# Context
```csharp
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptionsoptions) : base(options)
{
}public DbSetProjects { get; set; }
public DbSet Members { get; set; }
public DbSet Users { get; set; }
public DbSetRoles { get; set; }}
```# Seeding Data by Bogus
```csharp
public static class DataSeeding
{
public static void SeedData(this WebApplication app)
{
var scope = app.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService();// Seeding project
string projectId = Guid.NewGuid().ToString();
var fakerProject = new Faker()
.RuleFor(x => x.Name, f => f.Company.Bs())
.RuleFor(x => x.Id, f => projectId);Project project = fakerProject.Generate();
db.Projects.Add(project);// Seeding member
var fakerMember = new Faker()
.RuleFor(x => x.ProjectId, f => projectId)
.RuleFor(x => x.Name, f => f.Name.FirstName())
.RuleFor(x => x.LastName, f => f.Name.LastName())
.RuleFor(x => x.Title, f => f.Name.JobTitle())
.RuleFor(x => x.Id, f => Guid.NewGuid().ToString());List members = fakerMember.Generate(20);
db.Members.AddRange(members);// Seeding role
string adminId = Guid.NewGuid().ToString();
var fakeRoleAdmin = new Faker()
.RuleFor(x => x.Name, f => "ADMIN")
.RuleFor(x => x.Id, f => adminId);string managerId = Guid.NewGuid().ToString();
var fakeRoleManager = new Faker()
.RuleFor(x => x.Name, f => "MANAGER")
.RuleFor(x => x.Id, f => managerId);var admin = fakeRoleAdmin.Generate();
var manager = fakeRoleManager.Generate();
db.Roles.AddRange(admin, manager);// Seeding User
var fakeManager = new Faker()
.RuleFor(x => x.Id, f => Guid.NewGuid().ToString())
.RuleFor(x => x.Email, f => f.Person.Email)
.RuleFor(x => x.Password, f => "123456")
.RuleFor(x => x.Username, f => f.Person.UserName)
.RuleFor(x => x.RoleId, f => managerId);var user = fakeManager.Generate(1);
db.Users.AddRange(user);var fakeUser = new Faker()
.RuleFor(x => x.Id, f => Guid.NewGuid().ToString())
.RuleFor(x => x.Email, f => f.Person.Email)
.RuleFor(x => x.Password, f => "123456")
.RuleFor(x => x.Username, f => f.Person.UserName)
.RuleFor(x => x.RoleId, f => adminId);List users = fakeUser.Generate(5);
db.Users.AddRange(users);
db.SaveChanges();
}
```# Schemas
## Query.cs
```csharp
public class Query
{[UseProjection]
[UseFiltering]
[UseSorting]
public async Task> GetProjectAsync([Service] AppDbContext context)
{
return await Task.FromResult(context.Projects);
}[UseProjection]
[UseFiltering]
[UseSorting]
public async Task> GetMemberAsync([Service] AppDbContext context)
{
return await Task.FromResult(context.Members);
}[UseProjection]
[UseFiltering]
[UseSorting]
public async Task> GetUserAsync([Service] AppDbContext context)
{
return await Task.FromResult(context.Users);
}[UseProjection]
[UseFiltering]
[UseSorting]
[Authorize("HasRole", Roles = ["MANAGER"])]
public async Task> GetRoleAsync([Service] AppDbContext context)
{
return await Task.FromResult(context.Roles);
}public async Task LoginAsync(LoginInput input, [Service] AppDbContext context, [Service] TokenHelper tokenHelper)
{
var user = await context.Users.Include(x=>x.Role).SingleOrDefaultAsync(x => x.Username == input.Username && x.Password == input.Password);if (user is null)
{
throw new GraphQLException("Username or password is wrong!");
}var token = tokenHelper.GenerateToken(user);
return new LoginResponse(token.Token, token.TokenExpire, user);
}
}```
## Mutation.cs
```csharp
public class Mutation
{
public async Task CreateProjectAsync(CreateProjectInput input, CancellationToken cancellationToken, [Service] AppDbContext context)
{
var project = new Project
{
Id = Guid.NewGuid().ToString(),
Name = input.Name
};context.Add(project);
await context.SaveChangesAsync(cancellationToken);
return new CreateProjectOutput(project);
}public async Task UpdateProjectAsync(UpdateProjectInput input, CancellationToken cancellationToken, [Service] AppDbContext context)
{
var project = await context.Projects.SingleOrDefaultAsync(p => p.Id == input.Id);if (project is null)
throw new GraphQLException("Project not found!");project.Name = input.Name ?? default!;
context.Update(project);
return await context.SaveChangesAsync(cancellationToken) > 0;
}public async Task RemoveProjectAsync(string id, CancellationToken cancellationToken, [Service] AppDbContext context)
{
var project = await context.Projects.SingleOrDefaultAsync(p => p.Id == id);if (project is null)
throw new GraphQLException("Project not found!");context.Remove(project);
return await context.SaveChangesAsync(cancellationToken) > 0;
}// This method is for the Subscription's OnProjectCreated event
public async Task AddProjectWithEventAsync(CreateProjectInput input, [Service] AppDbContext context, [Service] ITopicEventSender eventSender, CancellationToken cancellationToken)
{
var project = new Project
{
Id = Guid.NewGuid().ToString(),
Name = input.Name
};context.Add(project);
await context.SaveChangesAsync(cancellationToken);await eventSender.SendAsync(nameof(Subscription.OnProjectCreated), project, cancellationToken);
return new CreateProjectOutput(project);
}
}
```## Subscription.cs
```csharp
public class Subscription
{
[Subscribe]
[Topic]
public Project OnProjectCreated([EventMessage] Project project)
{
return project;
}
}
```# Requests and responses
Attention! All the requests must to call by the Http POST method for usage the GraphQL## User-Role requests and responses

## Project requests and responses





## Member requests and responses



