авторизация
This commit is contained in:
		
							
								
								
									
										13
									
								
								CyberBoom/AuthOptions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								CyberBoom/AuthOptions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| using System.Text; | ||||
| using Microsoft.IdentityModel.Tokens; | ||||
|  | ||||
| public class AuthOptions | ||||
| { | ||||
|     public const string ISSUER = "MyAuthServer"; // издатель токена | ||||
|     public const string AUDIENCE = "MyAuthClient"; // потребитель токена | ||||
|     const string KEY = "mysupersecret_secretkey!123";   // ключ для шифрации | ||||
|  | ||||
|     public const int LIFETIME = 1; | ||||
|     public static SymmetricSecurityKey GetSymmetricSecurityKey() =>  | ||||
|         new SymmetricSecurityKey(Encoding.UTF8.GetBytes(KEY)); | ||||
| } | ||||
							
								
								
									
										52
									
								
								CyberBoom/BearerAccessTokenOptions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								CyberBoom/BearerAccessTokenOptions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| using Microsoft.IdentityModel.Tokens; | ||||
| using System.IdentityModel.Tokens.Jwt; | ||||
| using System.Security.Claims; | ||||
| using System.Text; | ||||
|  | ||||
| public class BearerAccessTokenOptions | ||||
| { | ||||
|     public string GetBearerToken(List<Claim> claims) => new JwtSecurityTokenHandler() | ||||
|         .WriteToken( | ||||
|             JwtSecurityToken(claims) | ||||
|          ); | ||||
|  | ||||
|  | ||||
|     public JwtSecurityToken JwtSecurityToken(List<Claim> claims) => new JwtSecurityToken( | ||||
|         issuer: Issuer, | ||||
|         audience: Audience, | ||||
|         notBefore: DateTime.UtcNow, | ||||
|         claims: claims, | ||||
|         expires: BearerTokenLifeTime, | ||||
|         signingCredentials: SigningCredentials | ||||
|     ); | ||||
|     public string SecurityAlgorithm { get; set; } = SecurityAlgorithms.HmacSha256; | ||||
|     public SigningCredentials SigningCredentials => new SigningCredentials(GetSymmetricSecurityKey, SecurityAlgorithm); | ||||
|     public DateTime BearerTokenLifeTime => DateTime.UtcNow.Add(TimeSpan.FromHours(Lifetime)); | ||||
|     public bool RequiredHttpsMetadata { get; set; } = false; | ||||
|     public string Issuer { get; set; } = "BackendHackathon"; | ||||
|     public string Audience { get; set; } = "BackendHackathon"; | ||||
|     public string Key { get; set; } = "5XGgEtGK9jsNxIUQvxef7wtAE6LwbLWd6LFwpryYoF9w=="; | ||||
|     public int Lifetime { get; set; } = 100; | ||||
|     public SymmetricSecurityKey GetSymmetricSecurityKey => new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Key)); | ||||
|  | ||||
|     public TokenValidationParameters TokenValidationParameters => new() | ||||
|     { | ||||
|         // укзывает, будет ли валидироваться издатель при валидации токена | ||||
|         ValidateIssuer = true, | ||||
|         // строка, представляющая издателя | ||||
|         ValidIssuer = Issuer, | ||||
|  | ||||
|         // будет ли валидироваться потребитель токена | ||||
|         ValidateAudience = true, | ||||
|         // установка потребителя токена | ||||
|         ValidAudience = Audience, | ||||
|         // будет ли валидироваться время существования | ||||
|         ValidateLifetime = true, | ||||
|  | ||||
|         ClockSkew = TimeSpan.Zero, | ||||
|         // установка ключа безопасности | ||||
|         IssuerSigningKey = GetSymmetricSecurityKey, | ||||
|         // валидация ключа безопасности | ||||
|         ValidateIssuerSigningKey = true, | ||||
|     }; | ||||
| } | ||||
							
								
								
									
										4
									
								
								CyberBoom/Consts.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								CyberBoom/Consts.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| public static class Consts | ||||
| { | ||||
|     public const char TOKENS_SEPORATOR = ';'; | ||||
| } | ||||
							
								
								
									
										72
									
								
								CyberBoom/Controllers/MeetingsController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								CyberBoom/Controllers/MeetingsController.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| using Mapster; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
|  | ||||
| namespace CyberBoom.Controllers; | ||||
|  | ||||
| [Authorize] | ||||
| [ApiController] | ||||
| [Route("/api/[controller]")] | ||||
| public class MeetingsController : ControllerBase | ||||
| { | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public MeetingsController(ApplicationContext applicationContext) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|      | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromForm] PostMeetingDto meeting) | ||||
|     { | ||||
|         await meeting.SpeackerImage.WriteFilesToDirectory(); | ||||
|         await meeting.PlaceImages.WriteFilesToDirectory(); | ||||
|         var meetingWrite = meeting.Adapt<Meeting>(); | ||||
|  | ||||
|         meetingWrite.SpeackerImage = meeting.SpeackerImage.JoinFileNames(); | ||||
|         meetingWrite.PlaceImages = meeting.PlaceImages.JoinFileNames(); | ||||
|  | ||||
|         await _applicationContext.Meetings.AddAsync(meetingWrite); | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(new { meetingWrite.Id }); | ||||
|     } | ||||
|  | ||||
|     [HttpPut] | ||||
|     public async Task<IActionResult> Put([FromForm] PutMeetingDto meeting) | ||||
|     { | ||||
|         await meeting.SpeackerImage.WriteFilesToDirectory(); | ||||
|         await meeting.PlaceImages.WriteFilesToDirectory(); | ||||
|  | ||||
|         var meetingWrite = meeting.Adapt<Meeting>(); | ||||
|  | ||||
|         meetingWrite.SpeackerImage = meeting.SpeackerImage.JoinFileNames(); | ||||
|         meetingWrite.PlaceImages = meeting.PlaceImages.JoinFileNames(); | ||||
|  | ||||
|         var findedMeeting = await _applicationContext.Meetings.FirstAsync(s => s.Id == meeting.Id); | ||||
|         findedMeeting = meetingWrite; | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [AllowAnonymous] | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var meeting = await _applicationContext.Meetings.FirstOrDefaultAsync(s => s.Id == id); | ||||
|  | ||||
|         return Ok(meeting); | ||||
|     } | ||||
|  | ||||
|     [AllowAnonymous] | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var meetings = _applicationContext.Meetings.AsNoTracking().Skip(offset).Take(limit); | ||||
|  | ||||
|         return Ok(meetings); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										63
									
								
								CyberBoom/Controllers/QuestionsController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								CyberBoom/Controllers/QuestionsController.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| using Mapster; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
|  | ||||
| namespace CyberBoom.Controllers; | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/[controller]")] | ||||
| public class QuestionsController : ControllerBase | ||||
| { | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public QuestionsController(ApplicationContext applicationContext) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromBody] PostQuestionDto question) | ||||
|     { | ||||
|         var dbWr = question.Adapt<Question>(); | ||||
|         await _applicationContext.Questions.AddAsync(dbWr); | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(new { dbWr.Id }); | ||||
|     } | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpPut] | ||||
|     public async Task<IActionResult> Put([FromBody] PutQuestionDto question) | ||||
|     { | ||||
|         var fReview = await _applicationContext.Questions.FirstAsync(r => r.Id == question.Id); | ||||
|  | ||||
|         fReview.Text = question.Text; | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var question = await _applicationContext.Questions.FirstAsync(s => s.Id == id); | ||||
|  | ||||
|         return Ok(question); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var questions = _applicationContext.Questions | ||||
|             .AsNoTracking() | ||||
|             .Include(c => c.User) | ||||
|             .Skip(offset) | ||||
|             .Take(limit); | ||||
|  | ||||
|         return Ok(questions); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										60
									
								
								CyberBoom/Controllers/ReactionsController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								CyberBoom/Controllers/ReactionsController.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| using Mapster; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
|  | ||||
| namespace CyberBoom.Controllers; | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/[controller]")] | ||||
| public class ReactionsController : ControllerBase | ||||
| { | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public ReactionsController(ApplicationContext applicationContext) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromBody] PostReactionDto reaction) | ||||
|     { | ||||
|         var dbWr = reaction.Adapt<Reaction>(); | ||||
|  | ||||
|         await _applicationContext.Reactions.AddAsync(dbWr); | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(new { dbWr.Id }); | ||||
|     } | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpDelete] | ||||
|     public async Task<IActionResult> Delete(string id) | ||||
|     { | ||||
|         var fReview = await _applicationContext.Reactions.FirstAsync(r => r.Id == id); | ||||
|  | ||||
|         _applicationContext.Reactions.Remove(fReview); | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var reaction = await _applicationContext.Reactions.FirstAsync(s => s.Id == id); | ||||
|  | ||||
|         return Ok(reaction); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var reactions = _applicationContext.Reactions.AsNoTracking().Skip(offset).Take(limit); | ||||
|  | ||||
|         return Ok(reactions); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										73
									
								
								CyberBoom/Controllers/ReviewsController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								CyberBoom/Controllers/ReviewsController.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| using Mapster; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
|  | ||||
| namespace CyberBoom.Controllers; | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/[controller]")] | ||||
| public class ReviewsController : ControllerBase | ||||
| { | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public ReviewsController(ApplicationContext applicationContext) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromBody] PostReviewDto review) | ||||
|     { | ||||
|         var dbWr = review.Adapt<Review>(); | ||||
|  | ||||
|         await _applicationContext.Reviews.AddAsync(dbWr); | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(new { dbWr.Id }); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpPut] | ||||
|     public async Task<IActionResult> Put([FromBody] PutReviewDto review) | ||||
|     { | ||||
|         var fReview = await _applicationContext.Reviews.FirstAsync(r => r.Id == review.Id); | ||||
|  | ||||
|         fReview.Text = review.Text; | ||||
|         fReview.Score = review.Score; | ||||
|         fReview.Date = review.Date; | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var review = await _applicationContext.Reviews.FirstAsync(s => s.Id == id); | ||||
|  | ||||
|         var user = await _applicationContext.Users.FirstAsync(s => s.Id == review.UserId); | ||||
|  | ||||
|         return Ok(new { review, user }); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var reviews = _applicationContext.Reviews | ||||
|             .AsNoTracking() | ||||
|             .Include(c => c.User) | ||||
|             .Skip(offset) | ||||
|             .Take(limit); | ||||
|  | ||||
|         // var userIds = reviews.Select(u => u.UserId).ToArray(); | ||||
|         // var users = _applicationContext.Users.Where(u => userIds.Contains(u.Id)); | ||||
|  | ||||
|         return Ok(reviews); | ||||
|     } | ||||
| } | ||||
| @@ -1,17 +1,19 @@ | ||||
| using System.IdentityModel.Tokens.Jwt; | ||||
| using Mapster; | ||||
| using System.Security.Claims; | ||||
| using Microsoft.AspNetCore.Authentication; | ||||
| using Microsoft.AspNetCore.Authentication.Google; | ||||
| using Microsoft.AspNetCore.Authentication.JwtBearer; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Identity; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.EntityFrameworkCore.Internal; | ||||
| using Microsoft.IdentityModel.Tokens; | ||||
| using static Consts; | ||||
|  | ||||
| namespace CyberBoom.Controllers; | ||||
|  | ||||
|  | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/[controller]")] | ||||
| public class UsersController : ControllerBase | ||||
| @@ -22,18 +24,41 @@ public class UsersController : ControllerBase | ||||
|  | ||||
|     private readonly RoleManager<IdentityRole> _roleManager; | ||||
|  | ||||
|     public UsersController(ApplicationContext applicationContext, UserManager<User> userManager, RoleManager<IdentityRole> roleManager) | ||||
|     public UsersController( | ||||
|         ApplicationContext applicationContext, | ||||
|         UserManager<User> userManager, | ||||
|         RoleManager<IdentityRole> roleManager | ||||
|     ) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|         _userManager = userManager; | ||||
|         _roleManager = roleManager; | ||||
|     } | ||||
|  | ||||
|     async Task AddUerToRole(User user, string role) | ||||
|     { | ||||
|         var isExists = await _roleManager.RoleExistsAsync(role); | ||||
|  | ||||
|         if (!isExists) | ||||
|         { | ||||
|             var roleResult = await _roleManager.CreateAsync(new IdentityRole(role)); | ||||
|             if (!roleResult.Succeeded) | ||||
|                 throw new Exception("cannot create role"); | ||||
|         } | ||||
|  | ||||
|         var addingRole = await _userManager.AddToRoleAsync(user, role); | ||||
|  | ||||
|         if (!addingRole.Succeeded) | ||||
|             throw new Exception("cannot create role"); | ||||
|     } | ||||
|  | ||||
|     [AllowAnonymous] | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromForm]UserPost user) | ||||
|     public async Task<IActionResult> Post([FromForm] UserPost user) | ||||
|     { | ||||
|         await user.Avatar.WriteFileToDirectory(); | ||||
|         var userWr = new User { | ||||
|         var userWr = new User | ||||
|         { | ||||
|             AvatarUrl = user.Avatar.FileName, | ||||
|             Fio = user.Fio, | ||||
|             Specialities = user.Specialities, | ||||
| @@ -41,26 +66,43 @@ public class UsersController : ControllerBase | ||||
|             UserName = user.Username | ||||
|         }; | ||||
|         var result = await _userManager.CreateAsync(userWr); | ||||
|         if(result.Succeeded) | ||||
|             return Ok( | ||||
|                 new { | ||||
|                     userWr.Id | ||||
|                 } | ||||
|             ); | ||||
|  | ||||
|         if (!result.Succeeded) | ||||
|             return BadRequest(result.Errors); | ||||
|  | ||||
|          | ||||
|  | ||||
|         var role = user.Username == "moderator" ? "модератор"  : "спикер"; | ||||
|  | ||||
|         await AddUerToRole(userWr, role); | ||||
|  | ||||
|         var token = GetToken(userWr, role); | ||||
|  | ||||
|         return Ok(new { userWr.Id, Token = token }); | ||||
|     } | ||||
|  | ||||
|     string GetToken(User user, string role) | ||||
|     { | ||||
|         var claims = new List<Claim> | ||||
|         { | ||||
|             new Claim(ClaimsIdentity.DefaultNameClaimType, user.UserName!), | ||||
|             new Claim(ClaimsIdentity.DefaultRoleClaimType, role) | ||||
|         }; | ||||
|         var bOpt = new BearerAccessTokenOptions(); | ||||
|         return bOpt.GetBearerToken(claims); | ||||
|     } | ||||
|  | ||||
|     [Authorize(Roles = "модератор")] | ||||
|     [HttpPut] | ||||
|     public async Task<IActionResult> Put([FromForm]UserPut user) | ||||
|     public async Task<IActionResult> Put([FromForm] UserPut user) | ||||
|     { | ||||
|         await user.Avatar.WriteFileToDirectory(); | ||||
|  | ||||
|         var fuser = await _userManager.FindByIdAsync(user.Id); | ||||
|  | ||||
|         if(fuser is null) | ||||
|         if (fuser is null) | ||||
|             throw new Exception("user not found"); | ||||
|  | ||||
|          | ||||
|         fuser.AvatarUrl = user.Avatar.FileName; | ||||
|         fuser.Fio = user.Fio; | ||||
|         fuser.Specialities = user.Specialities; | ||||
| @@ -68,19 +110,18 @@ public class UsersController : ControllerBase | ||||
|         fuser.UserName = user.Username; | ||||
|  | ||||
|         var result = await _userManager.UpdateAsync(fuser); | ||||
|         if(result.Succeeded) | ||||
|             return Ok( | ||||
|                 | ||||
|             ); | ||||
|         if (result.Succeeded) | ||||
|             return Ok(); | ||||
|         return BadRequest(result.Errors); | ||||
|     } | ||||
|  | ||||
|     [Authorize(Roles = "модератор")] | ||||
|     [HttpPost("moderator")] | ||||
|     public async Task<IActionResult> PostModerator([FromForm]UserPost user) | ||||
|     public async Task<IActionResult> PostModerator([FromForm] UserPost user) | ||||
|     { | ||||
|  | ||||
|         await user.Avatar.WriteFileToDirectory(); | ||||
|         var userWr = new User { | ||||
|         var userWr = new User | ||||
|         { | ||||
|             AvatarUrl = user.Avatar.FileName, | ||||
|             Fio = user.Fio, | ||||
|             Specialities = user.Specialities, | ||||
| @@ -88,480 +129,44 @@ public class UsersController : ControllerBase | ||||
|             UserName = user.Username | ||||
|         }; | ||||
|  | ||||
|          | ||||
|  | ||||
|         var result = await _userManager.CreateAsync(userWr); | ||||
|  | ||||
|         if(!result.Succeeded) | ||||
|         if (!result.Succeeded) | ||||
|             return BadRequest(result.Errors); | ||||
|  | ||||
|         var isExists = await _roleManager.RoleExistsAsync("модератор"); | ||||
|         var role = "модератор"; | ||||
|  | ||||
|         if(!isExists){ | ||||
|             var roleResult = await _roleManager.CreateAsync(new IdentityRole("модератор")); | ||||
|             if(!roleResult.Succeeded) | ||||
|                 throw new Exception("cannot create role"); | ||||
|         } | ||||
|              | ||||
|         var addingRole = await _userManager.AddToRoleAsync(userWr, "модератор"); | ||||
|  | ||||
|         if(!addingRole.Succeeded) | ||||
|             throw new Exception("cannot create role"); | ||||
|  | ||||
|         return Ok( | ||||
|                 new { | ||||
|                     userWr.Id | ||||
|                 } | ||||
|             ); | ||||
|         await AddUerToRole(userWr, role); | ||||
|         var token = GetToken(userWr, role); | ||||
|         return Ok(new { userWr.Id, Token = token }); | ||||
|     } | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> GetUserData(string id) | ||||
|     { | ||||
|         var user = await _userManager.FindByIdAsync(id); | ||||
|  | ||||
|         if(user is null) | ||||
|         if (user is null) | ||||
|             return BadRequest(); | ||||
|  | ||||
|         var role = await _userManager.GetRolesAsync(user); | ||||
|         return Ok(new { | ||||
|             user, | ||||
|             role | ||||
|         }); | ||||
|         return Ok(new { user, role }); | ||||
|     } | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpGet("stats")] | ||||
|     public async Task<IActionResult> GetUserStats(string id) | ||||
|     { | ||||
|         var user = await _userManager.FindByIdAsync(id); | ||||
|  | ||||
|         if(user is null) | ||||
|         if (user is null) | ||||
|             return BadRequest(); | ||||
|  | ||||
|         var stats = await _applicationContext.GetStatistic(id); | ||||
|  | ||||
|         var achievmnets = _applicationContext.Achievments.Where(c => c.UserId == id); | ||||
|  | ||||
|          | ||||
|         return Ok(new { | ||||
|             Stats = stats, | ||||
|             Achievments = achievmnets | ||||
|         }); | ||||
|         return Ok(new { Stats = stats, Achievments = achievmnets }); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/[controller]")] | ||||
| public class MeetingsController : ControllerBase | ||||
| { | ||||
|      | ||||
|  | ||||
|  | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public MeetingsController(ApplicationContext applicationContext) | ||||
|     { | ||||
|          | ||||
|          | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromForm]PostMeetingDto meeting) | ||||
|     { | ||||
|         await meeting.SpeackerImage.WriteFilesToDirectory(); | ||||
|         await meeting.PlaceImages.WriteFilesToDirectory(); | ||||
|         var meetingWrite = meeting.Adapt<Meeting>(); | ||||
|          | ||||
|         meetingWrite.SpeackerImage = meeting.SpeackerImage.JoinFileNames(); | ||||
|         meetingWrite.PlaceImages = meeting.PlaceImages.JoinFileNames(); | ||||
|  | ||||
|         await _applicationContext.Meetings.AddAsync(meetingWrite); | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|          | ||||
|         return Ok(new { | ||||
|             meetingWrite.Id | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     [HttpPut] | ||||
|     public async Task<IActionResult> Put([FromForm]PutMeetingDto meeting) | ||||
|     { | ||||
|         await meeting.SpeackerImage.WriteFilesToDirectory(); | ||||
|         await meeting.PlaceImages.WriteFilesToDirectory(); | ||||
|  | ||||
|         var meetingWrite = meeting.Adapt<Meeting>(); | ||||
|          | ||||
|         meetingWrite.SpeackerImage = meeting.SpeackerImage.JoinFileNames(); | ||||
|         meetingWrite.PlaceImages = meeting.PlaceImages.JoinFileNames(); | ||||
|          | ||||
|         var findedMeeting = await _applicationContext.Meetings.FirstAsync(s => s.Id == meeting.Id); | ||||
|         findedMeeting = meetingWrite; | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var meeting = await _applicationContext.Meetings.FirstOrDefaultAsync(s => s.Id == id); | ||||
|  | ||||
|          | ||||
|         return Ok(meeting); | ||||
|     } | ||||
|  | ||||
|      | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var meetings = _applicationContext.Meetings.AsNoTracking().Skip(offset).Take(limit); | ||||
|  | ||||
|          | ||||
|         return Ok(meetings); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/[controller]")] | ||||
| public class ReviewsController : ControllerBase | ||||
| { | ||||
|  | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public ReviewsController(ApplicationContext applicationContext) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromBody] PostReviewDto review) | ||||
|     { | ||||
|         var dbWr = review.Adapt<Review>(); | ||||
|          | ||||
|         await _applicationContext.Reviews.AddAsync(dbWr); | ||||
|          | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|          | ||||
|         return Ok(new { | ||||
|             dbWr.Id | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     [HttpPut] | ||||
|     public async Task<IActionResult> Put([FromBody]PutReviewDto review) | ||||
|     { | ||||
|          | ||||
|         var fReview = await _applicationContext.Reviews.FirstAsync(r => r.Id == review.Id); | ||||
|          | ||||
|          | ||||
|         fReview.Text = review.Text; | ||||
|         fReview.Score = review.Score; | ||||
|         fReview.Date = review.Date; | ||||
|  | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|          | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var review = await _applicationContext.Reviews.FirstAsync(s => s.Id == id); | ||||
|  | ||||
|         var user = await _applicationContext.Users.FirstAsync(s => s.Id == review.UserId); | ||||
|          | ||||
|         return Ok(new { | ||||
|             review, | ||||
|             user | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|      | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var reviews = _applicationContext.Reviews.AsNoTracking() | ||||
|             .Include(c => c.User) | ||||
|             .Skip(offset) | ||||
|             .Take(limit); | ||||
|  | ||||
|         // var userIds = reviews.Select(u => u.UserId).ToArray(); | ||||
|         // var users = _applicationContext.Users.Where(u => userIds.Contains(u.Id)); | ||||
|          | ||||
|         return Ok( | ||||
|             reviews | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/[controller]")] | ||||
| public class QuestionsController : ControllerBase | ||||
| { | ||||
|  | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public QuestionsController(ApplicationContext applicationContext) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromBody] PostQuestionDto question) | ||||
|     { | ||||
|         var dbWr = question.Adapt<Question>(); | ||||
|         await _applicationContext.Questions.AddAsync(dbWr); | ||||
|          | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|          | ||||
|         return Ok(new { | ||||
|             dbWr.Id | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     [HttpPut] | ||||
|     public async Task<IActionResult> Put([FromBody]PutQuestionDto question) | ||||
|     { | ||||
|          | ||||
|         var fReview = await _applicationContext.Questions.FirstAsync(r => r.Id == question.Id); | ||||
|          | ||||
|         fReview.Text = question.Text; | ||||
|          | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|          | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var question = await _applicationContext.Questions | ||||
|             .FirstAsync(s => s.Id == id); | ||||
|  | ||||
|          | ||||
|         return Ok(question); | ||||
|     } | ||||
|  | ||||
|      | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var questions = _applicationContext.Questions.AsNoTracking() | ||||
|             .Include(c => c.User) | ||||
|             .Skip(offset) | ||||
|             .Take(limit); | ||||
|  | ||||
|          | ||||
|         return Ok(questions); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/[controller]")] | ||||
| public class ReactionsController : ControllerBase | ||||
| { | ||||
|  | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public ReactionsController(ApplicationContext applicationContext) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromBody] PostReactionDto reaction) | ||||
|     { | ||||
|         var dbWr = reaction.Adapt<Reaction>(); | ||||
|          | ||||
|         await _applicationContext.Reactions.AddAsync(dbWr); | ||||
|          | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|          | ||||
|         return Ok(new { | ||||
|             dbWr.Id | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     [HttpDelete] | ||||
|     public async Task<IActionResult> Delete(string id) | ||||
|     { | ||||
|          | ||||
|         var fReview = await _applicationContext.Reactions.FirstAsync(r => r.Id == id); | ||||
|          | ||||
|          | ||||
|         _applicationContext.Reactions.Remove(fReview); | ||||
|  | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|          | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var reaction = await _applicationContext.Reactions | ||||
|             .FirstAsync(s => s.Id == id); | ||||
|  | ||||
|          | ||||
|         return Ok(reaction); | ||||
|     } | ||||
|  | ||||
|      | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var reactions = _applicationContext.Reactions.AsNoTracking() | ||||
|             .Skip(offset) | ||||
|             .Take(limit); | ||||
|          | ||||
|          | ||||
|         return Ok(reactions); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/users/meetings")] | ||||
| public class UserWriteToMetingController : ControllerBase | ||||
| { | ||||
|  | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public UserWriteToMetingController(ApplicationContext applicationContext) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromBody] PostUserWriteToMetingDto write) | ||||
|     { | ||||
|         var dbWr = write.Adapt<UserWriteToMeting>(); | ||||
|          | ||||
|         var meeting = await _applicationContext.Meetings.FirstAsync(m => m.Id == write.MeetingId); | ||||
|  | ||||
|  | ||||
|  | ||||
|         if(DateTime.UtcNow > meeting.Time) | ||||
|             return BadRequest(); | ||||
|  | ||||
|  | ||||
|  | ||||
|         await _applicationContext.UserWriteToMetings.AddAsync(dbWr); | ||||
|          | ||||
|          | ||||
|         var user = await _applicationContext.Users.FirstAsync(u => u.Id == write.UserId); | ||||
|  | ||||
|  | ||||
|         var newStats = await _applicationContext.GetStatistic(write.UserId); | ||||
|  | ||||
|          | ||||
|         var achievments = await WriteAchievment(newStats, write.UserId);         | ||||
|          | ||||
|          | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(new { | ||||
|             dbWr.Id, | ||||
|             Achievments = achievments | ||||
|         }); | ||||
|          | ||||
|     } | ||||
|  | ||||
|     async Task<List<Achievment>> WriteAchievment(StatsData stats, string userId) | ||||
|     { | ||||
|         List <Achievment> achievments = new List<Achievment>(); | ||||
|         if(stats.Count > 0 && stats.Count % 5 == 0) | ||||
|         { | ||||
|             var achievment = new Achievment{ | ||||
|                     Name = $"Редстоун Наблюдатель Level {stats.Count / 5}", | ||||
|                     Text = "Вы cамый настоящий Редстоун Наблюдатель из игры Майнкрафт, который не пропускате ни единой всречи!", | ||||
|                     UserId = userId | ||||
|                 }; | ||||
|             achievments.Add(achievment); | ||||
|             await _applicationContext.Achievments.AddAsync( | ||||
|                 achievment | ||||
|             ); | ||||
|         } | ||||
|         var achievedTags = stats.StatsByTag.Where(st => st.Count > 0 && st.Count % 5 == 0); | ||||
|         if(achievedTags.Count() > 0 && stats.Count % 5 == 0) | ||||
|         { | ||||
|              | ||||
|             foreach(var tag in achievedTags) | ||||
|             { | ||||
|                 var achievment = new Achievment{ | ||||
|                     Name = $"Вкачаю все в {tag.Tag} Level {tag.Count / 5}", | ||||
|                     Text = $"Вы нежалеете очки времени на ветку {tag.Tag}, продолжайте в том же духе!", | ||||
|                     UserId = userId | ||||
|                 }; | ||||
|                 achievments.Add(achievment); | ||||
|                 await _applicationContext.Achievments.AddAsync( | ||||
|                     achievment | ||||
|                 ); | ||||
|             } | ||||
|              | ||||
|         } | ||||
|         return achievments; | ||||
|     } | ||||
|  | ||||
|     [HttpDelete] | ||||
|     public async Task<IActionResult> Delete(string id) | ||||
|     { | ||||
|         var fReview = await _applicationContext.UserWriteToMetings.FirstAsync(r => r.Id == id); | ||||
|          | ||||
|          | ||||
|         var meeting = await _applicationContext.Meetings.FirstAsync(m => m.Id == fReview.MeetingId); | ||||
|  | ||||
|         if(DateTime.UtcNow > meeting.Time) | ||||
|             return BadRequest(); | ||||
|  | ||||
|         _applicationContext.UserWriteToMetings.Remove(fReview); | ||||
|  | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|          | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var review = await _applicationContext.UserWriteToMetings | ||||
|             .FirstAsync(s => s.Id == id); | ||||
|  | ||||
|          | ||||
|         return Ok(review); | ||||
|     } | ||||
|  | ||||
|      | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var reviews = _applicationContext.UserWriteToMetings.AsNoTracking() | ||||
|             .Skip(offset) | ||||
|             .Take(limit); | ||||
|  | ||||
|          | ||||
|         return Ok(reviews); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										114
									
								
								CyberBoom/Controllers/UserWriteToMetingController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								CyberBoom/Controllers/UserWriteToMetingController.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| using Mapster; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
|  | ||||
| namespace CyberBoom.Controllers; | ||||
|  | ||||
| [ApiController] | ||||
| [Route("/api/users/meetings")] | ||||
| public class UserWriteToMetingController : ControllerBase | ||||
| { | ||||
|     private readonly ApplicationContext _applicationContext; | ||||
|  | ||||
|     public UserWriteToMetingController(ApplicationContext applicationContext) | ||||
|     { | ||||
|         _applicationContext = applicationContext; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpPost] | ||||
|     public async Task<IActionResult> Post([FromBody] PostUserWriteToMetingDto write) | ||||
|     { | ||||
|         var dbWr = write.Adapt<UserWriteToMeting>(); | ||||
|  | ||||
|         var meeting = await _applicationContext.Meetings.FirstAsync(m => m.Id == write.MeetingId); | ||||
|  | ||||
|         if (DateTime.UtcNow > meeting.Time) | ||||
|             return BadRequest(); | ||||
|  | ||||
|         await _applicationContext.UserWriteToMetings.AddAsync(dbWr); | ||||
|  | ||||
|         var user = await _applicationContext.Users.FirstAsync(u => u.Id == write.UserId); | ||||
|  | ||||
|         var newStats = await _applicationContext.GetStatistic(write.UserId); | ||||
|  | ||||
|         var achievments = await WriteAchievment(newStats, write.UserId); | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(new { dbWr.Id, Achievments = achievments }); | ||||
|     } | ||||
|  | ||||
|     async Task<List<Achievment>> WriteAchievment(StatsData stats, string userId) | ||||
|     { | ||||
|         List<Achievment> achievments = new List<Achievment>(); | ||||
|         if (stats.Count > 0 && stats.Count % 5 == 0) | ||||
|         { | ||||
|             var achievment = new Achievment | ||||
|             { | ||||
|                 Name = $"Редстоун Наблюдатель Level {stats.Count / 5}", | ||||
|                 Text = | ||||
|                     "Вы cамый настоящий Редстоун Наблюдатель из игры Майнкрафт, который не пропускате ни единой всречи!", | ||||
|                 UserId = userId | ||||
|             }; | ||||
|             achievments.Add(achievment); | ||||
|             await _applicationContext.Achievments.AddAsync(achievment); | ||||
|         } | ||||
|         var achievedTags = stats.StatsByTag.Where(st => st.Count > 0 && st.Count % 5 == 0); | ||||
|         if (achievedTags.Count() > 0 && stats.Count % 5 == 0) | ||||
|         { | ||||
|             foreach (var tag in achievedTags) | ||||
|             { | ||||
|                 var achievment = new Achievment | ||||
|                 { | ||||
|                     Name = $"Вкачаю все в {tag.Tag} Level {tag.Count / 5}", | ||||
|                     Text = | ||||
|                         $"Вы нежалеете очки времени на ветку {tag.Tag}, продолжайте в том же духе!", | ||||
|                     UserId = userId | ||||
|                 }; | ||||
|                 achievments.Add(achievment); | ||||
|                 await _applicationContext.Achievments.AddAsync(achievment); | ||||
|             } | ||||
|         } | ||||
|         return achievments; | ||||
|     } | ||||
|  | ||||
|     [Authorize] | ||||
|     [HttpDelete] | ||||
|     public async Task<IActionResult> Delete(string id) | ||||
|     { | ||||
|         var fReview = await _applicationContext.UserWriteToMetings.FirstAsync(r => r.Id == id); | ||||
|  | ||||
|         var meeting = await _applicationContext.Meetings.FirstAsync(m => m.Id == fReview.MeetingId); | ||||
|  | ||||
|         if (DateTime.UtcNow > meeting.Time) | ||||
|             return BadRequest(); | ||||
|  | ||||
|         _applicationContext.UserWriteToMetings.Remove(fReview); | ||||
|  | ||||
|         await _applicationContext.SaveChangesAsync(); | ||||
|  | ||||
|         return Ok(); | ||||
|     } | ||||
|  | ||||
|     [HttpGet] | ||||
|     public async Task<IActionResult> Get(string id) | ||||
|     { | ||||
|         var review = await _applicationContext.UserWriteToMetings.FirstAsync(s => s.Id == id); | ||||
|  | ||||
|         return Ok(review); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("list")] | ||||
|     public IActionResult GetList(int offset, int limit) | ||||
|     { | ||||
|         var reviews = _applicationContext.UserWriteToMetings | ||||
|             .AsNoTracking() | ||||
|             .Skip(offset) | ||||
|             .Take(limit); | ||||
|  | ||||
|         return Ok(reviews); | ||||
|     } | ||||
| } | ||||
| @@ -1,25 +0,0 @@ | ||||
|  | ||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
| # Visual Studio Version 17 | ||||
| VisualStudioVersion = 17.5.002.0 | ||||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CyberBoom", "CyberBoom.csproj", "{A8F9D7D8-DDA5-479B-8735-00E706A5827F}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Any CPU = Debug|Any CPU | ||||
| 		Release|Any CPU = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| 		{A8F9D7D8-DDA5-479B-8735-00E706A5827F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{A8F9D7D8-DDA5-479B-8735-00E706A5827F}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{A8F9D7D8-DDA5-479B-8735-00E706A5827F}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{A8F9D7D8-DDA5-479B-8735-00E706A5827F}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||
| 		SolutionGuid = {674E1E42-AF3F-4DDA-A4F1-EDD84025DB24} | ||||
| 	EndGlobalSection | ||||
| EndGlobal | ||||
							
								
								
									
										86
									
								
								CyberBoom/DataHelpers.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								CyberBoom/DataHelpers.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using static Consts; | ||||
|  | ||||
| public static class DataHelpers | ||||
| { | ||||
|     public static string JoinFileNames(this IEnumerable<IFormFile> files) => files.Select(s => s.FileName).JoinStrings(); | ||||
|  | ||||
|     public static string JoinStrings(this IEnumerable<string> files) => String.Join(TOKENS_SEPORATOR, files.Select(s => s)); | ||||
|  | ||||
|     public static TimeSpan ParseDuration(this string duration)  | ||||
|     { | ||||
|         var durArr = duration.Split(TOKENS_SEPORATOR, StringSplitOptions.RemoveEmptyEntries); | ||||
|  | ||||
|         var hours = int.Parse(durArr.First()); | ||||
|         var minutes = int.Parse(durArr[1]); | ||||
|          | ||||
|         return new TimeSpan(hours, minutes, 0); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public static async Task WriteFileToDirectory(this IFormFile file) | ||||
|     { | ||||
|         var readStream = file.OpenReadStream(); | ||||
|         var memstream = new MemoryStream(); | ||||
|         await readStream.CopyToAsync(memstream); | ||||
|         await File.WriteAllBytesAsync(Path.Combine("cyber-boom-files", file.FileName), memstream.ToArray()); | ||||
|     } | ||||
|  | ||||
|     public static async Task WriteFilesToDirectory(this IEnumerable<IFormFile> files) | ||||
|     {    | ||||
|         foreach(var file in files) | ||||
|         { | ||||
|             await file.WriteFileToDirectory(); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|  | ||||
|     public static async Task<StatsData> GetStatistic(this ApplicationContext applicationContext, string id) | ||||
|     { | ||||
|         var specialities = await applicationContext.UserWriteToMetings.Where(c => c.UserId == id) | ||||
|             .Join(applicationContext.Meetings,  | ||||
|                 m => m.MeetingId,  | ||||
|                 m => m.Id, | ||||
|                 (c,m) => new { | ||||
|                     m.Tags, | ||||
|                     m.Id, | ||||
|                     m.Duration, | ||||
|                     m.Time | ||||
|                 } | ||||
|             ).Where(t => DateTime.UtcNow > t.Time).ToArrayAsync(); | ||||
|  | ||||
|         var selectedSpecialities = specialities.Select(s => new { | ||||
|             s.Id, | ||||
|             Tags = s.Tags.Split(TOKENS_SEPORATOR, StringSplitOptions.RemoveEmptyEntries), | ||||
|             Duration = s.Duration.ParseDuration().TotalHours | ||||
|         }); | ||||
|  | ||||
|         var allTags = selectedSpecialities.SelectMany(s => s.Tags).Distinct(); | ||||
|         var count = selectedSpecialities.Count(); | ||||
|          | ||||
|         StatsData stats = new StatsData{ | ||||
|             Count = count, | ||||
|             Hours = selectedSpecialities.Sum(m => m.Duration) * count | ||||
|               | ||||
|         }; | ||||
|         foreach(var tag in allTags) | ||||
|         { | ||||
|             //StatsData.TagStats | ||||
|             var specByTag = selectedSpecialities.Where(f => f.Tags.Contains(tag)); | ||||
|             var countByTag = specByTag.Count(); | ||||
|             var hours = selectedSpecialities.Sum(s => s.Duration) * countByTag; | ||||
|  | ||||
|             var stat = new StatsData.TagStats | ||||
|             { | ||||
|                 Count = countByTag, | ||||
|                 Tag = tag, | ||||
|                 Hours = hours | ||||
|             }; | ||||
|             stats.StatsByTag.Add(stat); | ||||
|         } | ||||
|  | ||||
|         | ||||
|          | ||||
|         return stats; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										13
									
								
								CyberBoom/DbContext/Achievment.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								CyberBoom/DbContext/Achievment.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| public class Achievment | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public string Name { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
| } | ||||
							
								
								
									
										47
									
								
								CyberBoom/DbContext/ApplicationContext.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								CyberBoom/DbContext/ApplicationContext.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| using Microsoft.AspNetCore.Identity.EntityFrameworkCore; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
|  | ||||
| public class ApplicationContext : IdentityDbContext<User> | ||||
| { | ||||
|     public DbSet<Meeting> Meetings { get; set; } | ||||
|  | ||||
|     public DbSet<Review> Reviews { get; set; } | ||||
|  | ||||
|     public DbSet<Reaction> Reactions { get; set; } | ||||
|      | ||||
|     public DbSet<UserWriteToMeting> UserWriteToMetings { get; set; } | ||||
|  | ||||
|     public DbSet<Question> Questions { get; set; } | ||||
|  | ||||
|  | ||||
|     public DbSet<Achievment> Achievments { get; set; } | ||||
|  | ||||
|     public ApplicationContext(DbContextOptions<ApplicationContext> options) | ||||
|         : base(options) | ||||
|     { | ||||
|         Database.EnsureCreated(); | ||||
|     } | ||||
|  | ||||
|     protected override void OnModelCreating(ModelBuilder builder) | ||||
|     { | ||||
|         base.OnModelCreating(builder); | ||||
|         builder.Entity<Meeting>().HasMany<Review>().WithOne().HasForeignKey(c => c.MeetingId); | ||||
|         builder.Entity<Meeting>().HasMany<Question>().WithOne().HasForeignKey(c => c.MeetingId); | ||||
|  | ||||
|          | ||||
|          | ||||
|          | ||||
|         builder.Entity<Reaction>().HasOne<User>().WithMany().HasForeignKey(c => c.UserId); | ||||
|         builder.Entity<Review>().HasOne(c => c.User).WithMany().HasForeignKey(c => c.UserId); | ||||
|  | ||||
|         builder.Entity<Question>().HasOne<Meeting>().WithMany().HasForeignKey(c => c.MeetingId); | ||||
|         builder.Entity<Question>().HasOne(c => c.User).WithMany().HasForeignKey(c => c.UserId); | ||||
|          | ||||
|         builder.Entity<Reaction>().HasOne<Question>().WithMany().HasForeignKey(c => c.QuestionId); | ||||
|  | ||||
|         builder.Entity<Meeting>().HasMany<UserWriteToMeting>().WithOne().HasForeignKey(c => c.MeetingId); | ||||
|         builder.Entity<UserWriteToMeting>().HasOne<User>().WithMany().HasForeignKey(c => c.UserId); | ||||
|      | ||||
|         builder.Entity<Achievment>().HasOne<User>().WithMany().HasForeignKey(c => c.UserId); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								CyberBoom/DbContext/Dtos/Meetings/PostMeetingDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								CyberBoom/DbContext/Dtos/Meetings/PostMeetingDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| public class PostMeetingDto | ||||
| { | ||||
|     public DateTime Time { get; set; } | ||||
|  | ||||
|     public string Title { get; set; } = null!; | ||||
|  | ||||
|     public string Theme { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerName { get; set; } = null!; | ||||
|  | ||||
|     public IEnumerable<IFormFile> SpeackerImage { get; set; } = null!; | ||||
|      | ||||
|     public IEnumerable<IFormFile> PlaceImages { get; set; } = null!; | ||||
|  | ||||
|  | ||||
|     public string Splecializations { get; set; } = null!; | ||||
|  | ||||
|     public string Type { get; set; } = "онлайн/офлайн"; | ||||
|  | ||||
|     public string SpeakerTelephone { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerEmail { get; set; } = null!; | ||||
|  | ||||
|     public string Tags { get; set; } = null!; | ||||
|  | ||||
|     public string Urls { get; set; } = null!; | ||||
|  | ||||
|     public string PlaceAdress { get; set; } = null!; | ||||
|  | ||||
|     public string Duration { get; set; } = null!; | ||||
| } | ||||
							
								
								
									
										33
									
								
								CyberBoom/DbContext/Dtos/Meetings/PutMeetingDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								CyberBoom/DbContext/Dtos/Meetings/PutMeetingDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| public class PutMeetingDto | ||||
| { | ||||
|     public String Id { get; set; } = null!; | ||||
|  | ||||
|     public DateTime Time { get; set; } | ||||
|  | ||||
|     public string Title { get; set; } = null!; | ||||
|  | ||||
|     public string Theme { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerName { get; set; } = null!; | ||||
|  | ||||
|     public IEnumerable<IFormFile> SpeackerImage { get; set; } = null!; | ||||
|  | ||||
|     public IEnumerable<IFormFile> PlaceImages { get; set; } = null!; | ||||
|  | ||||
|     public string Splecializations { get; set; } = null!; | ||||
|  | ||||
|  | ||||
|     public string Type { get; set; } = "онлайн/офлайн"; | ||||
|  | ||||
|     public string SpeakerTelephone { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerEmail { get; set; } = null!; | ||||
|  | ||||
|     public string Tags { get; set; } = null!; | ||||
|  | ||||
|     public string Urls { get; set; } = null!; | ||||
|  | ||||
|     public string PlaceAdress { get; set; } = null!; | ||||
|  | ||||
|     public string Duration { get; set; } = null!; | ||||
| } | ||||
							
								
								
									
										8
									
								
								CyberBoom/DbContext/Dtos/Questions/PostQuestionDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								CyberBoom/DbContext/Dtos/Questions/PostQuestionDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| public class PostQuestionDto | ||||
| { | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public string MeetingId { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
| } | ||||
							
								
								
									
										6
									
								
								CyberBoom/DbContext/Dtos/Questions/PutQuestionDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								CyberBoom/DbContext/Dtos/Questions/PutQuestionDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| public class PutQuestionDto | ||||
| { | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
| } | ||||
							
								
								
									
										9
									
								
								CyberBoom/DbContext/Dtos/Reaction/PostReactionDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								CyberBoom/DbContext/Dtos/Reaction/PostReactionDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| public class PostReactionDto | ||||
| { | ||||
|  | ||||
|     public string QuestionId { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public bool IsLike { get; set; } = true; | ||||
| } | ||||
							
								
								
									
										14
									
								
								CyberBoom/DbContext/Dtos/Review/PostReviewDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								CyberBoom/DbContext/Dtos/Review/PostReviewDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| public class PostReviewDto | ||||
| { | ||||
|     public String MeetingId { get; set; } = null!; | ||||
|      | ||||
|     public String UserId { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public int Score { get; set; } = 0; | ||||
|  | ||||
|     DateTime _date; | ||||
|      | ||||
|     public DateTime Date { get => _date; set => _date = value.ToUniversalTime(); } | ||||
| } | ||||
							
								
								
									
										12
									
								
								CyberBoom/DbContext/Dtos/Review/PutReviewDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								CyberBoom/DbContext/Dtos/Review/PutReviewDto.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| public class PutReviewDto | ||||
| { | ||||
|     public string Id { get; set; } = null!; | ||||
|      | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public int Score { get; set; } = 0; | ||||
|  | ||||
|     DateTime _date; | ||||
|      | ||||
|     public DateTime Date { get => _date; set => _date = value.ToUniversalTime(); } | ||||
| } | ||||
| @@ -0,0 +1,6 @@ | ||||
| public class PostUserWriteToMetingDto | ||||
| { | ||||
|     public String UserId { get; set; }  = null!; | ||||
|  | ||||
|     public String MeetingId { get; set; } = null!; | ||||
| } | ||||
							
								
								
									
										17
									
								
								CyberBoom/DbContext/Dtos/User/StatsData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								CyberBoom/DbContext/Dtos/User/StatsData.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| public class StatsData | ||||
| { | ||||
|     public double Hours{ get; set; } | ||||
|  | ||||
|     public int Count { get; set; } | ||||
|  | ||||
|     public List<TagStats> StatsByTag { get; set; } = new List<TagStats>(); | ||||
|  | ||||
|     public class TagStats | ||||
|     { | ||||
|         public string Tag { get; set; } = null!; | ||||
|  | ||||
|         public int Count { get; set; } | ||||
|  | ||||
|         public double Hours { get; set; } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										12
									
								
								CyberBoom/DbContext/Dtos/User/UserPost.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								CyberBoom/DbContext/Dtos/User/UserPost.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| public class UserPost | ||||
| { | ||||
|     public IFormFile Avatar { get; set; } = null!; | ||||
|  | ||||
|     public string Fio { get; set; } = null!; | ||||
|  | ||||
|     public string Username { get; set; } = null!; | ||||
|  | ||||
|     public string Specialities { get; set; } = null!; | ||||
|  | ||||
|     public string TelegramBotUrl { get; set; } = null!; | ||||
| } | ||||
							
								
								
									
										14
									
								
								CyberBoom/DbContext/Dtos/User/UserPut.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								CyberBoom/DbContext/Dtos/User/UserPut.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| public class UserPut | ||||
| { | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public IFormFile Avatar { get; set; } = null!; | ||||
|  | ||||
|     public string Fio { get; set; } = null!; | ||||
|  | ||||
|     public string Username { get; set; } = null!; | ||||
|  | ||||
|     public string Specialities { get; set; } = null!; | ||||
|  | ||||
|     public string TelegramBotUrl { get; set; } = null!; | ||||
| } | ||||
							
								
								
									
										37
									
								
								CyberBoom/DbContext/Meeting.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								CyberBoom/DbContext/Meeting.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| public class Meeting | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public String Id { get; set; } = null!; | ||||
|  | ||||
|     public DateTime Time { get; set; } | ||||
|  | ||||
|     public string Title { get; set; } = null!; | ||||
|  | ||||
|     public string Theme { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerName { get; set; } = null!; | ||||
|  | ||||
|     public string SpeackerImage { get; set; } = null!; | ||||
|  | ||||
|     public string Splecializations { get; set; } = null!; //speacker specilization | ||||
|  | ||||
|      | ||||
|     public string Type { get; set; } = "онлайн/офлайн"; | ||||
|  | ||||
|     public string SpeakerTelephone { get; set; } = null!; | ||||
|  | ||||
|  | ||||
|     public string PlaceImages { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerEmail { get; set; } = null!; | ||||
|  | ||||
|     public string Tags { get; set; } = null!; | ||||
|  | ||||
|     public string Urls { get; set; } = null!; | ||||
|  | ||||
|     public string PlaceAdress { get; set; } = null!; | ||||
|  | ||||
|     public string Duration { get; set; } = null!; | ||||
| }    | ||||
							
								
								
									
										15
									
								
								CyberBoom/DbContext/Question.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								CyberBoom/DbContext/Question.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| public class Question | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public string MeetingId { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public User User { get; set; } = null!; | ||||
| } | ||||
							
								
								
									
										13
									
								
								CyberBoom/DbContext/Reaction.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								CyberBoom/DbContext/Reaction.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| public class Reaction | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string QuestionId { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public bool IsLike { get; set; } = true; | ||||
| } | ||||
							
								
								
									
										21
									
								
								CyberBoom/DbContext/Review.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								CyberBoom/DbContext/Review.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| public class Review | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string MeetingId { get; set; } = null!; | ||||
|      | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public int Score { get; set; } = 0; | ||||
|  | ||||
|     public User User { get; set; } = null!; | ||||
|  | ||||
|     DateTime _date; | ||||
|      | ||||
|     public DateTime Date { get => _date; set => _date = value.ToUniversalTime(); } | ||||
| } | ||||
| @@ -1,7 +1,4 @@ | ||||
| using Microsoft.AspNetCore.Identity; | ||||
| using Microsoft.AspNetCore.Identity.EntityFrameworkCore; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
|  | ||||
| public class User : IdentityUser | ||||
| @@ -18,341 +15,3 @@ public class User : IdentityUser | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| public class UserPost | ||||
| { | ||||
|     public IFormFile Avatar { get; set; } = null!; | ||||
|  | ||||
|     public string Fio { get; set; } = null!; | ||||
|  | ||||
|     public string Username { get; set; } = null!; | ||||
|  | ||||
|     public string Specialities { get; set; } = null!; | ||||
|  | ||||
|     public string TelegramBotUrl { get; set; } = null!; | ||||
| } | ||||
|  | ||||
| public class StatsData | ||||
| { | ||||
|     public double Hours{ get; set; } | ||||
|  | ||||
|     public int Count { get; set; } | ||||
|  | ||||
|     public List<TagStats> StatsByTag { get; set; } = new List<TagStats>(); | ||||
|  | ||||
|     public class TagStats | ||||
|     { | ||||
|         public string Tag { get; set; } = null!; | ||||
|  | ||||
|         public int Count { get; set; } | ||||
|  | ||||
|         public double Hours { get; set; } | ||||
|     } | ||||
| } | ||||
|  | ||||
| public class UserPut | ||||
| { | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public IFormFile Avatar { get; set; } = null!; | ||||
|  | ||||
|     public string Fio { get; set; } = null!; | ||||
|  | ||||
|     public string Username { get; set; } = null!; | ||||
|  | ||||
|     public string Specialities { get; set; } = null!; | ||||
|  | ||||
|     public string TelegramBotUrl { get; set; } = null!; | ||||
| } | ||||
|  | ||||
| public class PostMeetingDto | ||||
| { | ||||
|     public DateTime Time { get; set; } | ||||
|  | ||||
|     public string Title { get; set; } = null!; | ||||
|  | ||||
|     public string Theme { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerName { get; set; } = null!; | ||||
|  | ||||
|     public IEnumerable<IFormFile> SpeackerImage { get; set; } = null!; | ||||
|      | ||||
|     public IEnumerable<IFormFile> PlaceImages { get; set; } = null!; | ||||
|  | ||||
|  | ||||
|     public string Splecializations { get; set; } = null!; | ||||
|  | ||||
|     public string Type { get; set; } = "онлайн/офлайн"; | ||||
|  | ||||
|     public string SpeakerTelephone { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerEmail { get; set; } = null!; | ||||
|  | ||||
|     public string Tags { get; set; } = null!; | ||||
|  | ||||
|     public string Urls { get; set; } = null!; | ||||
|  | ||||
|     public string PlaceAdress { get; set; } = null!; | ||||
|  | ||||
|     public string Duration { get; set; } = null!; | ||||
| } | ||||
|  | ||||
|  | ||||
| public class UserWriteToMeting | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public String Id { get; set; } = null!; | ||||
|  | ||||
|     public String UserId { get; set; } = null!; | ||||
|  | ||||
|     public String MeetingId { get; set; } = null!; | ||||
| } | ||||
|  | ||||
|  | ||||
| public class PostUserWriteToMetingDto | ||||
| { | ||||
|     public String UserId { get; set; }  = null!; | ||||
|  | ||||
|     public String MeetingId { get; set; } = null!; | ||||
| } | ||||
|  | ||||
|  | ||||
| public class PutMeetingDto | ||||
| { | ||||
|     public String Id { get; set; } = null!; | ||||
|  | ||||
|     public DateTime Time { get; set; } | ||||
|  | ||||
|     public string Title { get; set; } = null!; | ||||
|  | ||||
|     public string Theme { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerName { get; set; } = null!; | ||||
|  | ||||
|     public IEnumerable<IFormFile> SpeackerImage { get; set; } = null!; | ||||
|  | ||||
|     public IEnumerable<IFormFile> PlaceImages { get; set; } = null!; | ||||
|  | ||||
|     public string Splecializations { get; set; } = null!; | ||||
|  | ||||
|  | ||||
|     public string Type { get; set; } = "онлайн/офлайн"; | ||||
|  | ||||
|     public string SpeakerTelephone { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerEmail { get; set; } = null!; | ||||
|  | ||||
|     public string Tags { get; set; } = null!; | ||||
|  | ||||
|     public string Urls { get; set; } = null!; | ||||
|  | ||||
|     public string PlaceAdress { get; set; } = null!; | ||||
|  | ||||
|     public string Duration { get; set; } = null!; | ||||
| } | ||||
|  | ||||
|  | ||||
| public class Meeting | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public String Id { get; set; } = null!; | ||||
|  | ||||
|     public DateTime Time { get; set; } | ||||
|  | ||||
|     public string Title { get; set; } = null!; | ||||
|  | ||||
|     public string Theme { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerName { get; set; } = null!; | ||||
|  | ||||
|     public string SpeackerImage { get; set; } = null!; | ||||
|  | ||||
|     public string Splecializations { get; set; } = null!; //speacker specilization | ||||
|  | ||||
|      | ||||
|     public string Type { get; set; } = "онлайн/офлайн"; | ||||
|  | ||||
|     public string SpeakerTelephone { get; set; } = null!; | ||||
|  | ||||
|  | ||||
|     public string PlaceImages { get; set; } = null!; | ||||
|  | ||||
|     public string SpeakerEmail { get; set; } = null!; | ||||
|  | ||||
|     public string Tags { get; set; } = null!; | ||||
|  | ||||
|     public string Urls { get; set; } = null!; | ||||
|  | ||||
|     public string PlaceAdress { get; set; } = null!; | ||||
|  | ||||
|     public string Duration { get; set; } = null!; | ||||
| }    | ||||
|  | ||||
|  | ||||
| public class PostReviewDto | ||||
| { | ||||
|     public String MeetingId { get; set; } = null!; | ||||
|      | ||||
|     public String UserId { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public int Score { get; set; } = 0; | ||||
|  | ||||
|     DateTime _date; | ||||
|      | ||||
|     public DateTime Date { get => _date; set => _date = value.ToUniversalTime(); } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| public class PutReviewDto | ||||
| { | ||||
|     public string Id { get; set; } = null!; | ||||
|      | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public int Score { get; set; } = 0; | ||||
|  | ||||
|     DateTime _date; | ||||
|      | ||||
|     public DateTime Date { get => _date; set => _date = value.ToUniversalTime(); } | ||||
| } | ||||
|  | ||||
|  | ||||
| public class PostQuestionDto | ||||
| { | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public string MeetingId { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
| } | ||||
|  | ||||
|  | ||||
| public class PutQuestionDto | ||||
| { | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
| } | ||||
|  | ||||
| public class Question | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public string MeetingId { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public User User { get; set; } = null!; | ||||
| } | ||||
|  | ||||
|  | ||||
| public class Review | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string MeetingId { get; set; } = null!; | ||||
|      | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
|  | ||||
|     public int Score { get; set; } = 0; | ||||
|  | ||||
|     public User User { get; set; } = null!; | ||||
|  | ||||
|     DateTime _date; | ||||
|      | ||||
|     public DateTime Date { get => _date; set => _date = value.ToUniversalTime(); } | ||||
| } | ||||
|  | ||||
|  | ||||
| public class Achievment | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public string Name { get; set; } = null!; | ||||
|  | ||||
|     public string Text { get; set; } = null!; | ||||
| } | ||||
|  | ||||
|  | ||||
| public class PostReactionDto | ||||
| { | ||||
|  | ||||
|     public string QuestionId { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public bool IsLike { get; set; } = true; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| public class Reaction | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public string Id { get; set; } = null!; | ||||
|  | ||||
|     public string QuestionId { get; set; } = null!; | ||||
|  | ||||
|     public string UserId { get; set; } = null!; | ||||
|  | ||||
|     public bool IsLike { get; set; } = true; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| public class ApplicationContext : IdentityDbContext<User> | ||||
| { | ||||
|     public DbSet<Meeting> Meetings { get; set; } | ||||
|  | ||||
|     public DbSet<Review> Reviews { get; set; } | ||||
|  | ||||
|     public DbSet<Reaction> Reactions { get; set; } | ||||
|      | ||||
|     public DbSet<UserWriteToMeting> UserWriteToMetings { get; set; } | ||||
|  | ||||
|     public DbSet<Question> Questions { get; set; } | ||||
|  | ||||
|  | ||||
|     public DbSet<Achievment> Achievments { get; set; } | ||||
|  | ||||
|     public ApplicationContext(DbContextOptions<ApplicationContext> options) | ||||
|         : base(options) | ||||
|     { | ||||
|         Database.EnsureCreated(); | ||||
|     } | ||||
|  | ||||
|     protected override void OnModelCreating(ModelBuilder builder) | ||||
|     { | ||||
|         base.OnModelCreating(builder); | ||||
|         builder.Entity<Meeting>().HasMany<Review>().WithOne().HasForeignKey(c => c.MeetingId); | ||||
|         builder.Entity<Meeting>().HasMany<Question>().WithOne().HasForeignKey(c => c.MeetingId); | ||||
|  | ||||
|          | ||||
|          | ||||
|          | ||||
|         builder.Entity<Reaction>().HasOne<User>().WithMany().HasForeignKey(c => c.UserId); | ||||
|         builder.Entity<Review>().HasOne(c => c.User).WithMany().HasForeignKey(c => c.UserId); | ||||
|  | ||||
|         builder.Entity<Question>().HasOne<Meeting>().WithMany().HasForeignKey(c => c.MeetingId); | ||||
|         builder.Entity<Question>().HasOne(c => c.User).WithMany().HasForeignKey(c => c.UserId); | ||||
|          | ||||
|         builder.Entity<Reaction>().HasOne<Question>().WithMany().HasForeignKey(c => c.QuestionId); | ||||
|  | ||||
|         builder.Entity<Meeting>().HasMany<UserWriteToMeting>().WithOne().HasForeignKey(c => c.MeetingId); | ||||
|         builder.Entity<UserWriteToMeting>().HasOne<User>().WithMany().HasForeignKey(c => c.UserId); | ||||
|      | ||||
|         builder.Entity<Achievment>().HasOne<User>().WithMany().HasForeignKey(c => c.UserId); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								CyberBoom/DbContext/UserWriteToMeting.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								CyberBoom/DbContext/UserWriteToMeting.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| public class UserWriteToMeting | ||||
| { | ||||
|     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
|     public String Id { get; set; } = null!; | ||||
|  | ||||
|     public String UserId { get; set; } = null!; | ||||
|  | ||||
|     public String MeetingId { get; set; } = null!; | ||||
| } | ||||
| @@ -1,11 +1,12 @@ | ||||
| using System.Text; | ||||
| using Microsoft.AspNetCore.Authentication.JwtBearer; | ||||
| using Microsoft.AspNetCore.Identity; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.IdentityModel.Tokens; | ||||
| using Mapster; | ||||
| using static Consts; | ||||
| using Microsoft.Extensions.FileProviders; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Mvc.Authorization; | ||||
| using Microsoft.OpenApi.Models; | ||||
|  | ||||
|  | ||||
| TypeAdapterConfig<PutMeetingDto, Meeting>.NewConfig().Map(d => d.SpeackerImage, s => s.SpeackerImage.JoinFileNames());  | ||||
| @@ -31,44 +32,51 @@ builder.Services.AddDbContext<ApplicationContext>(options => | ||||
| builder.Services.AddIdentity<User, IdentityRole>() | ||||
| .AddEntityFrameworkStores<ApplicationContext>(); | ||||
|  | ||||
| builder.Services.AddAuthorization(); | ||||
| builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) | ||||
|  .AddJwtBearer(options => | ||||
|     { | ||||
|         options.TokenValidationParameters = new TokenValidationParameters | ||||
|         { | ||||
|             // указывает, будет ли валидироваться издатель при валидации токена | ||||
|             ValidateIssuer = true, | ||||
|             // строка, представляющая издателя | ||||
|             ValidIssuer = AuthOptions.ISSUER, | ||||
|             // будет ли валидироваться потребитель токена | ||||
|             ValidateAudience = true, | ||||
|             // установка потребителя токена | ||||
|             ValidAudience = AuthOptions.AUDIENCE, | ||||
|             // будет ли валидироваться время существования | ||||
|             ValidateLifetime = true, | ||||
|             // установка ключа безопасности | ||||
|             IssuerSigningKey = AuthOptions.GetSymmetricSecurityKey(), | ||||
|             // валидация ключа безопасности | ||||
|             ValidateIssuerSigningKey = true, | ||||
|          }; | ||||
|     }); | ||||
| // .AddGoogle(googleOptions => | ||||
| // { | ||||
| //     googleOptions.ClientId = configuration["Authentication:Google:ClientId"] ?? throw new NullReferenceException(""); | ||||
| //     googleOptions.ClientSecret = configuration["Authentication:Google:ClientSecret"] ?? throw new NullReferenceException(""); | ||||
| // }); | ||||
| builder.Services.AddAuthentication(opt => { | ||||
|     opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; | ||||
|     opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; | ||||
| }) | ||||
| .AddJwtBearer(options => | ||||
| { | ||||
|     var bearerOptions = new BearerAccessTokenOptions(); | ||||
|     options.RequireHttpsMetadata = bearerOptions.RequiredHttpsMetadata; | ||||
|     options.TokenValidationParameters = bearerOptions.TokenValidationParameters; | ||||
| }); | ||||
|  | ||||
| // builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) | ||||
| //     .AddEntityFrameworkStores<ApplicationContext>(); | ||||
| // builder.Services.AddRazorPages(); | ||||
|  | ||||
|  | ||||
|  | ||||
| builder.Services.AddControllers(); | ||||
| // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | ||||
| builder.Services.AddEndpointsApiExplorer(); | ||||
| builder.Services.AddSwaggerGen(); | ||||
| builder.Services.AddSwaggerGen(c => | ||||
| { | ||||
|     c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); | ||||
|  | ||||
|     c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme | ||||
|     { | ||||
|         Description = "JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below.", | ||||
|         Name = "Authorization", | ||||
|         In = ParameterLocation.Header, | ||||
|         Type = SecuritySchemeType.ApiKey, | ||||
|         Scheme = "Bearer" | ||||
|     }); | ||||
|  | ||||
|     c.AddSecurityRequirement(new OpenApiSecurityRequirement | ||||
|     { | ||||
|         { | ||||
|             new OpenApiSecurityScheme | ||||
|             { | ||||
|                 Reference = new OpenApiReference | ||||
|                 { | ||||
|                     Type = ReferenceType.SecurityScheme, | ||||
|                     Id = "Bearer" | ||||
|                 } | ||||
|             }, | ||||
|             new string[] {} | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
| builder.Services.AddCors(); | ||||
|  | ||||
| var app = builder.Build(); | ||||
| @@ -97,100 +105,3 @@ app.MapControllers(); | ||||
| //app.MapRazorPages(); | ||||
|  | ||||
| app.Run(); | ||||
|  | ||||
| public class AuthOptions | ||||
| { | ||||
|     public const string ISSUER = "MyAuthServer"; // издатель токена | ||||
|     public const string AUDIENCE = "MyAuthClient"; // потребитель токена | ||||
|     const string KEY = "mysupersecret_secretkey!123";   // ключ для шифрации | ||||
|     public static SymmetricSecurityKey GetSymmetricSecurityKey() =>  | ||||
|         new SymmetricSecurityKey(Encoding.UTF8.GetBytes(KEY)); | ||||
| } | ||||
|  | ||||
| public static class Consts | ||||
| { | ||||
|     public const char TOKENS_SEPORATOR = ';'; | ||||
| } | ||||
| public static class DataHelpers | ||||
| { | ||||
|     public static string JoinFileNames(this IEnumerable<IFormFile> files) => files.Select(s => s.FileName).JoinStrings(); | ||||
|  | ||||
|     public static string JoinStrings(this IEnumerable<string> files) => String.Join(TOKENS_SEPORATOR, files.Select(s => s)); | ||||
|  | ||||
|     public static TimeSpan ParseDuration(this string duration)  | ||||
|     { | ||||
|         var durArr = duration.Split(TOKENS_SEPORATOR, StringSplitOptions.RemoveEmptyEntries); | ||||
|  | ||||
|         var hours = int.Parse(durArr.First()); | ||||
|         var minutes = int.Parse(durArr[1]); | ||||
|          | ||||
|         return new TimeSpan(hours, minutes, 0); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public static async Task WriteFileToDirectory(this IFormFile file) | ||||
|     { | ||||
|         var readStream = file.OpenReadStream(); | ||||
|         var memstream = new MemoryStream(); | ||||
|         await readStream.CopyToAsync(memstream); | ||||
|         await File.WriteAllBytesAsync(Path.Combine("cyber-boom-files", file.FileName), memstream.ToArray()); | ||||
|     } | ||||
|  | ||||
|     public static async Task WriteFilesToDirectory(this IEnumerable<IFormFile> files) | ||||
|     {    | ||||
|         foreach(var file in files) | ||||
|         { | ||||
|             await file.WriteFileToDirectory(); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|  | ||||
|     public static async Task<StatsData> GetStatistic(this ApplicationContext applicationContext, string id) | ||||
|     { | ||||
|         var specialities = await applicationContext.UserWriteToMetings.Where(c => c.UserId == id) | ||||
|             .Join(applicationContext.Meetings,  | ||||
|                 m => m.MeetingId,  | ||||
|                 m => m.Id, | ||||
|                 (c,m) => new { | ||||
|                     m.Tags, | ||||
|                     m.Id, | ||||
|                     m.Duration, | ||||
|                     m.Time | ||||
|                 } | ||||
|             ).Where(t => DateTime.UtcNow > t.Time).ToArrayAsync(); | ||||
|  | ||||
|         var selectedSpecialities = specialities.Select(s => new { | ||||
|             s.Id, | ||||
|             Tags = s.Tags.Split(TOKENS_SEPORATOR, StringSplitOptions.RemoveEmptyEntries), | ||||
|             Duration = s.Duration.ParseDuration().TotalHours | ||||
|         }); | ||||
|  | ||||
|         var allTags = selectedSpecialities.SelectMany(s => s.Tags).Distinct(); | ||||
|         var count = selectedSpecialities.Count(); | ||||
|          | ||||
|         StatsData stats = new StatsData{ | ||||
|             Count = count, | ||||
|             Hours = selectedSpecialities.Sum(m => m.Duration) * count | ||||
|               | ||||
|         }; | ||||
|         foreach(var tag in allTags) | ||||
|         { | ||||
|             //StatsData.TagStats | ||||
|             var specByTag = selectedSpecialities.Where(f => f.Tags.Contains(tag)); | ||||
|             var countByTag = specByTag.Count(); | ||||
|             var hours = selectedSpecialities.Sum(s => s.Duration) * countByTag; | ||||
|  | ||||
|             var stat = new StatsData.TagStats | ||||
|             { | ||||
|                 Count = countByTag, | ||||
|                 Tag = tag, | ||||
|                 Hours = hours | ||||
|             }; | ||||
|             stats.StatsByTag.Add(stat); | ||||
|         } | ||||
|  | ||||
|         | ||||
|          | ||||
|         return stats; | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user