Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config/fix mentor enity #10

Merged
merged 2 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using MBS_COMMAND.API.DependencyInjection.Options;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;

Expand All @@ -9,9 +12,74 @@ public static class SwaggerExtensions
{
public static void AddSwaggerAPI(this IServiceCollection services)
{
services.AddSwaggerGen();
services.AddSwaggerGen(c =>
{
c.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme()
{
Description = @"JWT Authorization header using the Bearer scheme.

Enter 'Bearer' [space] and then your token in the text input below.

Example: 'Bearer 12345abcdef'",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = JwtBearerDefaults.AuthenticationScheme
});

c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = JwtBearerDefaults.AuthenticationScheme
},
Scheme = "oauth2",
Name = JwtBearerDefaults.AuthenticationScheme,
In = ParameterLocation.Header,
},
new List<string>()
}
});

c.OperationFilter<SwaggerFormDataOperationFilter>();

c.EnableAnnotations();

});
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
}

public class SwaggerFormDataOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var formParameters = context.MethodInfo
.GetParameters()
.Where(p => p.GetCustomAttributes(true)
.Any(attr => attr.GetType() == typeof(FromFormAttribute)))
.ToList();

if (formParameters.Any())
{
foreach (var param in formParameters)
{
operation.RequestBody = new OpenApiRequestBody
{
Content = {
["multipart/form-data"] = new OpenApiMediaType
{
Schema = context.SchemaGenerator.GenerateSchema(param.ParameterType, context.SchemaRepository)
}
}
};
}
}
}
}

public static void UseSwaggerAPI(this WebApplication app)
{
Expand Down
12 changes: 12 additions & 0 deletions MBS-COMMAND.API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
using MBS_COMMAND.API.Middlewares;
using MBS_COMMAND.Application.DependencyInjection.Extensions;
using MBS_COMMAND.Infrastucture.DependencyInjection.Extensions;
using MBS_COMMAND.Infrastucture.DependencyInjection.Options;
using MBS_COMMAND.Persistence.DependencyInjection.Extensions;
using MBS_COMMAND.Persistence.DependencyInjection.Options;
using MicroElements.Swashbuckle.FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Http.Features;
using Serilog;

var builder = WebApplication.CreateBuilder(args);
Expand Down Expand Up @@ -44,6 +46,13 @@
builder.Services.AddMediatRApplication();
builder.Services.AddAutoMapperApplication();

builder.Services.Configure<FormOptions>(options =>
{
options.ValueLengthLimit = int.MaxValue;
options.MultipartBodyLengthLimit = long.MaxValue;
options.MultipartHeadersLengthLimit = int.MaxValue;
});

// Persistence Layer
builder.Services.AddInterceptorPersistence();
builder.Services.ConfigureSqlServerRetryOptionsPersistence(builder.Configuration.GetSection(nameof(SqlServerRetryOptions)));
Expand All @@ -61,6 +70,9 @@
builder.Services.AddJwtAuthenticationAPI(builder.Configuration);

// Infrastructure Layer
builder.Services.AddServicesInfrastructure();
builder.Services.AddRedisInfrastructure(builder.Configuration);
builder.Services.ConfigureCloudinaryOptionsInfrastucture(builder.Configuration.GetSection(nameof(CloudinaryOptions)));

// Add Middleware => Remember using middleware
builder.Services.AddTransient<ExceptionHandlingMiddleware>();
Expand Down
5 changes: 5 additions & 0 deletions MBS-COMMAND.API/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"initialInterval": "00:00:05",
"intervalIncrement": "00:00:10"
},
"CloudinaryOptions" : {
"CloudName": "dejf8mmou",
"ApiKey": "352838987568689",
"ApiSecret": "a3GLia6ovHgc-8xit46QEs8usWY"
},
"SqlServerRetryOptions": {
"MaxRetryCount": 5,
"MaxRetryDelay": "00:00:05",
Expand Down
5 changes: 5 additions & 0 deletions MBS-COMMAND.API/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"initialInterval": "00:00:05",
"intervalIncrement": "00:00:10"
},
"CloudinaryOptions" : {
"CloudName": "dejf8mmou",
"ApiKey": "352838987568689",
"ApiSecret": "a3GLia6ovHgc-8xit46QEs8usWY"
},
"SqlServerRetryOptions": {
"MaxRetryCount": 5,
"MaxRetryDelay": "00:00:05",
Expand Down
1 change: 1 addition & 0 deletions MBS_COMMAND.Application/MBS_COMMAND.Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="FluentValidation" Version="11.9.2" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.2" />
<PackageReference Include="MBS_CONTRACT.SHARE" Version="1.0.1" />
<PackageReference Include="MediatR" Version="12.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using MBS_AUTHORIZATION.Domain.Entities;
using MBS_COMMAND.Application.Abstractions;
using MBS_COMMAND.Contract.Abstractions.Messages;
using MBS_COMMAND.Contract.Abstractions.Shared;
using MBS_COMMAND.Contract.Services.MentorSkills;
using MBS_COMMAND.Domain.Abstractions.Repositories;
using MBS_COMMAND.Domain.Entities;

namespace MBS_COMMAND.Application.UserCases.Commands.MentorSkills;

public class CreateMentorSkillsCommandHandler : ICommandHandler<Command.CreateMentorSkillsCommand>
{
private readonly IRepositoryBase<Domain.Entities.MentorSkills, Guid> _mentorSkillsRepository;
private readonly IRepositoryBase<Skill, Guid> _skillsRepository;
private readonly IRepositoryBase<User, Guid> _userRepository;
private readonly IRepositoryBase<Certificate, Guid> _cetificateRepository;
private readonly IMediaService _mediaService;

public CreateMentorSkillsCommandHandler(IRepositoryBase<Domain.Entities.MentorSkills, Guid> mentorSkillsRepository, IRepositoryBase<Skill, Guid> skillsRepository, IMediaService mediaService, IRepositoryBase<Certificate, Guid> cetificateRepository, IRepositoryBase<User, Guid> userRepository)
{
_mentorSkillsRepository = mentorSkillsRepository;
_skillsRepository = skillsRepository;
_mediaService = mediaService;
_cetificateRepository = cetificateRepository;
_userRepository = userRepository;
}

public async Task<Result> Handle(Command.CreateMentorSkillsCommand request, CancellationToken cancellationToken)
{
var skill = await _skillsRepository.FindByIdAsync(request.SkillId, cancellationToken, x => x.Category);

if (skill is null) return Result.Failure(new Error("404", $"Not Exist Skill with Id: {request.SkillId}"));

var mentor = await _userRepository.FindSingleAsync(x => x.Id.Equals(request.MentorId) && x.IsDeleted == false, cancellationToken);

if (mentor is null) return Result.Failure(new Error("404", $"Not Mentor with Id: {request.MentorId}"));

var mentorSkill = new Domain.Entities.MentorSkills()
{
Id = Guid.NewGuid(),
SkillId = request.SkillId,
UserId = request.MentorId,
};

_mentorSkillsRepository.Add(mentorSkill);

var tasks = request.ProductImages.Select(x => _mediaService.UploadImageAsync(x));
var result = await Task.WhenAll(tasks);

var certificates = result.Select(x => new Certificate()
{
Id = Guid.NewGuid(),
MentorSkillsId = mentorSkill.Id,
Name = "12312",
Description = "123123",
ImageUrl = x
}).ToList();

_cetificateRepository.AddRange(certificates);

// mentorSkill.CreateMentor(mentor);
mentorSkill.CreateMentorSkills(mentor.Id, skill, certificates);

return Result.Success("Adding Skill For Mentor Successfully !");
}
}
3 changes: 3 additions & 0 deletions MBS_COMMAND.Contract/MBS_COMMAND.Contract.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
<PackageReference Include="FluentValidation" Version="11.9.2" />
<PackageReference Include="MassTransit" Version="8.2.5" />
<PackageReference Include="MediatR" Version="12.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.7" />
<PackageReference Include="MongoDB.Bson" Version="2.28.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.8.1" />
</ItemGroup>

<ItemGroup>
<Folder Include="Services\MentorSkills\Validators\" />
<Folder Include="Services\Slots\" />
<Folder Include="Services\Users\Validators\" />
</ItemGroup>
Expand Down
21 changes: 21 additions & 0 deletions MBS_COMMAND.Contract/Services/MentorSkills/Command.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.ComponentModel;
using MBS_COMMAND.Contract.Abstractions.Messages;
using Microsoft.AspNetCore.Http;
using Swashbuckle.AspNetCore.Annotations;


namespace MBS_COMMAND.Contract.Services.MentorSkills;

public class Command
{
public record CreateMentorSkillsCommand : ICommand
{
public Guid SkillId { get; set; }

[SwaggerSchema(ReadOnly = true)]
[DefaultValue("e824c924-e441-4367-a03b-8dd13223f76f")]
public Guid MentorId { get; set; }

public IFormFileCollection ProductImages { get; set; }
}
}
25 changes: 25 additions & 0 deletions MBS_COMMAND.Contract/Services/MentorSkills/DomainEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using MBS_COMMAND.Contract.Abstractions.Messages;

namespace MBS_COMMAND.Contract.Services.MentorSkills;

public class DomainEvent
{
public record MentorSkillsCreated(Guid IdEvent, Guid Id, Guid MentorId,
Skill skill, IReadOnlyCollection<Certificate> Certificates) : IDomainEvent, ICommand;

public class Skill
{
public string Name { get; set; }
public string Description { get; set; }
public string CateogoryType { get; set; }
public DateTimeOffset CreatedOnUtc { get; set; }
public DateTimeOffset? ModifiedOnUtc { get; set; }
}

public class Certificate
{
public string Name { get; set; }
public string Description { get; set; }
public string ImageUrl { get; set; }
}
}
6 changes: 6 additions & 0 deletions MBS_COMMAND.Contract/Services/MentorSkills/Query.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace MBS_COMMAND.Contract.Services.MentorSkills;

public class Query
{

}
6 changes: 6 additions & 0 deletions MBS_COMMAND.Contract/Services/MentorSkills/Response.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace MBS_COMMAND.Contract.Services.MentorSkills;

public class Response
{

}
6 changes: 5 additions & 1 deletion MBS_COMMAND.Contract/Services/Mentors/DomainEvent.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
using MBS_COMMAND.Contract.Abstractions.Messages;

namespace MBS_COMMAND.Contract.Services.Mentors;

public class DomainEvent
{

public record MentorCreated(Guid IdEvent, Guid Id, string Email,
string FullName, int Role, int Points, int Status,
DateTimeOffset CreatedOnUtc, bool IsDeleted) : IDomainEvent;
}
7 changes: 4 additions & 3 deletions MBS_COMMAND.Domain/Abstractions/Aggregates/AggregateRoot.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
using MBS_COMMAND.Contract.Abstractions.Messages;
using MBS_COMMAND.Domain.Abstractions.Entities;
using DomainEventShared = MBS_CONTRACT.SHARE.Abstractions.Messages;

namespace MBS_COMMAND.Domain.Abstractions.Aggregates;

public abstract class AggregateRoot<T> : Entity<T>
{
private readonly List<IDomainEvent> _domainEvents = new();
private readonly List<DomainEventShared.IDomainEvent> _domainEvents = new();

public IReadOnlyCollection<IDomainEvent> GetDomainEvents() => _domainEvents.ToList();
public IReadOnlyCollection<DomainEventShared.IDomainEvent> GetDomainEvents() => _domainEvents.ToList();

public void ClearDomainEvents() => _domainEvents.Clear();

protected void RaiseDomainEvent(IDomainEvent domainEvent) =>
protected void RaiseDomainEvent(DomainEventShared.IDomainEvent domainEvent) =>
_domainEvents.Add(domainEvent);
}
2 changes: 1 addition & 1 deletion MBS_COMMAND.Domain/Abstractions/Entities/Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace MBS_COMMAND.Domain.Abstractions.Entities;

public abstract class Entity<T> : IEntity<T>
{
public T Id { get; protected set; }
public T Id { get; set; }

public bool IsDeleted { get; protected set; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ namespace MBS_COMMAND.Domain.Abstractions.Repositories;

public interface IRepositoryBase<TEntity, in TKey> where TEntity : class
{
Task<TEntity> FindByIdAsync(TKey id, CancellationToken cancellationToken = default, params Expression<Func<TEntity, object>>[] includeProperties);
Task<TEntity?> FindByIdAsync(TKey id, CancellationToken cancellationToken = default, params Expression<Func<TEntity, object>>[] includeProperties);

Task<TEntity> FindSingleAsync(Expression<Func<TEntity, bool>>? predicate = null, CancellationToken cancellationToken = default, params Expression<Func<TEntity, object>>[] includeProperties);
Task<TEntity?> FindSingleAsync(Expression<Func<TEntity, bool>>? predicate = null, CancellationToken cancellationToken = default, params Expression<Func<TEntity, object>>[] includeProperties);

IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>>? predicate = null, params Expression<Func<TEntity, object>>[] includeProperties);

void Add(TEntity entity);

void AddRange(IEnumerable<TEntity> entities);

void Update(TEntity entity);

void UpdateRange(IEnumerable<TEntity> entities);

void Remove(TEntity entity);

Expand Down
2 changes: 1 addition & 1 deletion MBS_COMMAND.Domain/Entities/Certificate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class Certificate : Entity<Guid>,IAuditableEntity
public string Name { get; set; }
public string Description { get; set; }
public string ImageUrl { get; set; }
public Guid MetorSkillsId { get; set; }
public Guid MentorSkillsId { get; set; }
public virtual MentorSkills MentorSkills { get; set; }
public DateTimeOffset CreatedOnUtc { get ; set ; }
public DateTimeOffset? ModifiedOnUtc { get ; set ; }
Expand Down
2 changes: 1 addition & 1 deletion MBS_COMMAND.Domain/Entities/Group.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public Group(string name, string stack, Guid? mentorId)
public static Group Create(string name, string stack, Guid? mentorId)
{
var G = new Group(name, stack, mentorId);
G.RaiseDomainEvent(new Contract.Services.Groups.DomainEvents.GroupCreated(Guid.NewGuid(), G.Id, G.Name, G.MentorId, G.Stack));
//G.RaiseDomainEvent(new Contract.Services.Groups.DomainEvents.GroupCreated(Guid.NewGuid(), G.Id, G.Name, G.MentorId, G.Stack));
return G;
}

Expand Down
Loading
Loading