авторизация
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 System.IdentityModel.Tokens.Jwt; | ||||||
| using Mapster; | using System.Security.Claims; | ||||||
| using Microsoft.AspNetCore.Authentication; | using Microsoft.AspNetCore.Authentication; | ||||||
| using Microsoft.AspNetCore.Authentication.Google; | using Microsoft.AspNetCore.Authentication.Google; | ||||||
| using Microsoft.AspNetCore.Authentication.JwtBearer; | using Microsoft.AspNetCore.Authentication.JwtBearer; | ||||||
|  | using Microsoft.AspNetCore.Authorization; | ||||||
| using Microsoft.AspNetCore.Identity; | using Microsoft.AspNetCore.Identity; | ||||||
| using Microsoft.AspNetCore.Mvc; | using Microsoft.AspNetCore.Mvc; | ||||||
| using Microsoft.EntityFrameworkCore; |  | ||||||
| using Microsoft.EntityFrameworkCore.Internal; | using Microsoft.EntityFrameworkCore.Internal; | ||||||
| using Microsoft.IdentityModel.Tokens; | using Microsoft.IdentityModel.Tokens; | ||||||
| using static Consts; | using static Consts; | ||||||
|  |  | ||||||
| namespace CyberBoom.Controllers; | namespace CyberBoom.Controllers; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| [ApiController] | [ApiController] | ||||||
| [Route("/api/[controller]")] | [Route("/api/[controller]")] | ||||||
| public class UsersController : ControllerBase | public class UsersController : ControllerBase | ||||||
| @@ -22,18 +24,41 @@ public class UsersController : ControllerBase | |||||||
|  |  | ||||||
|     private readonly RoleManager<IdentityRole> _roleManager; |     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; |         _applicationContext = applicationContext; | ||||||
|         _userManager = userManager; |         _userManager = userManager; | ||||||
|         _roleManager = roleManager; |         _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] |     [HttpPost] | ||||||
|     public async Task<IActionResult> Post([FromForm] UserPost user) |     public async Task<IActionResult> Post([FromForm] UserPost user) | ||||||
|     { |     { | ||||||
|         await user.Avatar.WriteFileToDirectory(); |         await user.Avatar.WriteFileToDirectory(); | ||||||
|         var userWr = new User { |         var userWr = new User | ||||||
|  |         { | ||||||
|             AvatarUrl = user.Avatar.FileName, |             AvatarUrl = user.Avatar.FileName, | ||||||
|             Fio = user.Fio, |             Fio = user.Fio, | ||||||
|             Specialities = user.Specialities, |             Specialities = user.Specialities, | ||||||
| @@ -41,15 +66,33 @@ public class UsersController : ControllerBase | |||||||
|             UserName = user.Username |             UserName = user.Username | ||||||
|         }; |         }; | ||||||
|         var result = await _userManager.CreateAsync(userWr); |         var result = await _userManager.CreateAsync(userWr); | ||||||
|         if(result.Succeeded) |  | ||||||
|             return Ok( |         if (!result.Succeeded) | ||||||
|                 new { |  | ||||||
|                     userWr.Id |  | ||||||
|                 } |  | ||||||
|             ); |  | ||||||
|             return BadRequest(result.Errors); |             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] |     [HttpPut] | ||||||
|     public async Task<IActionResult> Put([FromForm] UserPut user) |     public async Task<IActionResult> Put([FromForm] UserPut user) | ||||||
|     { |     { | ||||||
| @@ -60,7 +103,6 @@ public class UsersController : ControllerBase | |||||||
|         if (fuser is null) |         if (fuser is null) | ||||||
|             throw new Exception("user not found"); |             throw new Exception("user not found"); | ||||||
|  |  | ||||||
|          |  | ||||||
|         fuser.AvatarUrl = user.Avatar.FileName; |         fuser.AvatarUrl = user.Avatar.FileName; | ||||||
|         fuser.Fio = user.Fio; |         fuser.Fio = user.Fio; | ||||||
|         fuser.Specialities = user.Specialities; |         fuser.Specialities = user.Specialities; | ||||||
| @@ -69,18 +111,17 @@ public class UsersController : ControllerBase | |||||||
|  |  | ||||||
|         var result = await _userManager.UpdateAsync(fuser); |         var result = await _userManager.UpdateAsync(fuser); | ||||||
|         if (result.Succeeded) |         if (result.Succeeded) | ||||||
|             return Ok( |             return Ok(); | ||||||
|                 |  | ||||||
|             ); |  | ||||||
|         return BadRequest(result.Errors); |         return BadRequest(result.Errors); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [Authorize(Roles = "модератор")] | ||||||
|     [HttpPost("moderator")] |     [HttpPost("moderator")] | ||||||
|     public async Task<IActionResult> PostModerator([FromForm] UserPost user) |     public async Task<IActionResult> PostModerator([FromForm] UserPost user) | ||||||
|     { |     { | ||||||
|  |  | ||||||
|         await user.Avatar.WriteFileToDirectory(); |         await user.Avatar.WriteFileToDirectory(); | ||||||
|         var userWr = new User { |         var userWr = new User | ||||||
|  |         { | ||||||
|             AvatarUrl = user.Avatar.FileName, |             AvatarUrl = user.Avatar.FileName, | ||||||
|             Fio = user.Fio, |             Fio = user.Fio, | ||||||
|             Specialities = user.Specialities, |             Specialities = user.Specialities, | ||||||
| @@ -88,33 +129,19 @@ public class UsersController : ControllerBase | |||||||
|             UserName = user.Username |             UserName = user.Username | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|          |  | ||||||
|  |  | ||||||
|         var result = await _userManager.CreateAsync(userWr); |         var result = await _userManager.CreateAsync(userWr); | ||||||
|  |  | ||||||
|         if (!result.Succeeded) |         if (!result.Succeeded) | ||||||
|             return BadRequest(result.Errors); |             return BadRequest(result.Errors); | ||||||
|  |  | ||||||
|         var isExists = await _roleManager.RoleExistsAsync("модератор"); |         var role = "модератор"; | ||||||
|  |  | ||||||
|         if(!isExists){ |         await AddUerToRole(userWr, role); | ||||||
|             var roleResult = await _roleManager.CreateAsync(new IdentityRole("модератор")); |         var token = GetToken(userWr, role); | ||||||
|             if(!roleResult.Succeeded) |         return Ok(new { userWr.Id, Token = token }); | ||||||
|                 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 |  | ||||||
|                 } |  | ||||||
|             ); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [Authorize] | ||||||
|     [HttpGet] |     [HttpGet] | ||||||
|     public async Task<IActionResult> GetUserData(string id) |     public async Task<IActionResult> GetUserData(string id) | ||||||
|     { |     { | ||||||
| @@ -124,12 +151,10 @@ public class UsersController : ControllerBase | |||||||
|             return BadRequest(); |             return BadRequest(); | ||||||
|  |  | ||||||
|         var role = await _userManager.GetRolesAsync(user); |         var role = await _userManager.GetRolesAsync(user); | ||||||
|         return Ok(new { |         return Ok(new { user, role }); | ||||||
|             user, |  | ||||||
|             role |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [Authorize] | ||||||
|     [HttpGet("stats")] |     [HttpGet("stats")] | ||||||
|     public async Task<IActionResult> GetUserStats(string id) |     public async Task<IActionResult> GetUserStats(string id) | ||||||
|     { |     { | ||||||
| @@ -142,426 +167,6 @@ public class UsersController : ControllerBase | |||||||
|  |  | ||||||
|         var achievmnets = _applicationContext.Achievments.Where(c => c.UserId == 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; | ||||||
| using Microsoft.AspNetCore.Identity.EntityFrameworkCore; |  | ||||||
| using Microsoft.EntityFrameworkCore; |  | ||||||
| using System.ComponentModel.DataAnnotations.Schema; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| public class User : IdentityUser | 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.Authentication.JwtBearer; | ||||||
| using Microsoft.AspNetCore.Identity; | using Microsoft.AspNetCore.Identity; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using Microsoft.IdentityModel.Tokens; |  | ||||||
| using Mapster; | using Mapster; | ||||||
| using static Consts; | using static Consts; | ||||||
| using Microsoft.Extensions.FileProviders; | 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());  | 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>() | builder.Services.AddIdentity<User, IdentityRole>() | ||||||
| .AddEntityFrameworkStores<ApplicationContext>(); | .AddEntityFrameworkStores<ApplicationContext>(); | ||||||
|  |  | ||||||
| builder.Services.AddAuthorization(); | builder.Services.AddAuthentication(opt => { | ||||||
| builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) |     opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; | ||||||
|  |     opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; | ||||||
|  | }) | ||||||
| .AddJwtBearer(options => | .AddJwtBearer(options => | ||||||
| { | { | ||||||
|         options.TokenValidationParameters = new TokenValidationParameters |     var bearerOptions = new BearerAccessTokenOptions(); | ||||||
|         { |     options.RequireHttpsMetadata = bearerOptions.RequiredHttpsMetadata; | ||||||
|             // указывает, будет ли валидироваться издатель при валидации токена |     options.TokenValidationParameters = bearerOptions.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.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) |  | ||||||
| //     .AddEntityFrameworkStores<ApplicationContext>(); |  | ||||||
| // builder.Services.AddRazorPages(); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| builder.Services.AddControllers(); | builder.Services.AddControllers(); | ||||||
| // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | ||||||
| builder.Services.AddEndpointsApiExplorer(); | 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(); | builder.Services.AddCors(); | ||||||
|  |  | ||||||
| var app = builder.Build(); | var app = builder.Build(); | ||||||
| @@ -97,100 +105,3 @@ app.MapControllers(); | |||||||
| //app.MapRazorPages(); | //app.MapRazorPages(); | ||||||
|  |  | ||||||
| app.Run(); | 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