forked from CyberBloom/CyberBloomBackend
сделал авторизация доабвил оптимизацию
This commit is contained in:
parent
6a32bc4fa9
commit
b4b5bfc1ed
@ -6,7 +6,9 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Internal;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using static Consts;
|
||||||
|
|
||||||
namespace CyberBoom.Controllers;
|
namespace CyberBoom.Controllers;
|
||||||
|
|
||||||
@ -14,10 +16,6 @@ namespace CyberBoom.Controllers;
|
|||||||
[Route("/api/[controller]")]
|
[Route("/api/[controller]")]
|
||||||
public class UsersController : ControllerBase
|
public class UsersController : ControllerBase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private readonly ApplicationContext _applicationContext;
|
private readonly ApplicationContext _applicationContext;
|
||||||
|
|
||||||
private readonly UserManager<User> _userManager;
|
private readonly UserManager<User> _userManager;
|
||||||
@ -131,6 +129,25 @@ public class UsersController : ControllerBase
|
|||||||
role
|
role
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("stats")]
|
||||||
|
public async Task<IActionResult> GetUserStats(string id)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByIdAsync(id);
|
||||||
|
|
||||||
|
if(user is null)
|
||||||
|
return BadRequest();
|
||||||
|
|
||||||
|
var stats = await _applicationContext.GetStatistic(id);
|
||||||
|
|
||||||
|
var achievmnets = _applicationContext.Achievments.Where(c => c.UserId == id);
|
||||||
|
|
||||||
|
|
||||||
|
return Ok(new {
|
||||||
|
Stats = stats,
|
||||||
|
Achievments = achievmnets
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,7 +219,7 @@ public class MeetingsController : ControllerBase
|
|||||||
[HttpGet("list")]
|
[HttpGet("list")]
|
||||||
public IActionResult GetList(int offset, int limit)
|
public IActionResult GetList(int offset, int limit)
|
||||||
{
|
{
|
||||||
var meetings = _applicationContext.Meetings.Skip(offset).Take(limit);
|
var meetings = _applicationContext.Meetings.AsNoTracking().Skip(offset).Take(limit);
|
||||||
|
|
||||||
|
|
||||||
return Ok(meetings);
|
return Ok(meetings);
|
||||||
@ -272,7 +289,7 @@ public class ReviewsController : ControllerBase
|
|||||||
[HttpGet("list")]
|
[HttpGet("list")]
|
||||||
public IActionResult GetList(int offset, int limit)
|
public IActionResult GetList(int offset, int limit)
|
||||||
{
|
{
|
||||||
var reviews = _applicationContext.Reviews
|
var reviews = _applicationContext.Reviews.AsNoTracking()
|
||||||
.Include(c => c.User)
|
.Include(c => c.User)
|
||||||
.Skip(offset)
|
.Skip(offset)
|
||||||
.Take(limit);
|
.Take(limit);
|
||||||
@ -341,7 +358,7 @@ public class QuestionsController : ControllerBase
|
|||||||
[HttpGet("list")]
|
[HttpGet("list")]
|
||||||
public IActionResult GetList(int offset, int limit)
|
public IActionResult GetList(int offset, int limit)
|
||||||
{
|
{
|
||||||
var questions = _applicationContext.Questions
|
var questions = _applicationContext.Questions.AsNoTracking()
|
||||||
.Include(c => c.User)
|
.Include(c => c.User)
|
||||||
.Skip(offset)
|
.Skip(offset)
|
||||||
.Take(limit);
|
.Take(limit);
|
||||||
@ -398,32 +415,23 @@ public class ReactionsController : ControllerBase
|
|||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> Get(string id)
|
public async Task<IActionResult> Get(string id)
|
||||||
{
|
{
|
||||||
var review = await _applicationContext.Reviews
|
var reaction = await _applicationContext.Reactions
|
||||||
.FirstAsync(s => s.Id == id);
|
.FirstAsync(s => s.Id == id);
|
||||||
|
|
||||||
var user = await _applicationContext.Users.FirstAsync(s => s.Id == review.UserId);
|
|
||||||
return Ok(new {
|
return Ok(reaction);
|
||||||
review,
|
|
||||||
user
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("list")]
|
[HttpGet("list")]
|
||||||
public IActionResult GetList(int offset, int limit)
|
public IActionResult GetList(int offset, int limit)
|
||||||
{
|
{
|
||||||
var reviews = _applicationContext.Reviews
|
var reactions = _applicationContext.Reactions.AsNoTracking()
|
||||||
.Skip(offset)
|
.Skip(offset)
|
||||||
.Take(limit);
|
.Take(limit);
|
||||||
|
|
||||||
var users = _applicationContext.Users.Where(u => reviews.Select(u => u.UserId).Contains(u.Id));
|
|
||||||
|
|
||||||
return Ok(
|
return Ok(reactions);
|
||||||
reviews.Select(s => new {
|
|
||||||
review = s,
|
|
||||||
user = users.First(u => u.Id == s.UserId)
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,22 +457,83 @@ public class UserWriteToMetingController : ControllerBase
|
|||||||
{
|
{
|
||||||
var dbWr = write.Adapt<UserWriteToMeting>();
|
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);
|
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();
|
await _applicationContext.SaveChangesAsync();
|
||||||
|
|
||||||
return Ok(new {
|
return Ok(new {
|
||||||
dbWr.Id
|
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]
|
[HttpDelete]
|
||||||
public async Task<IActionResult> Delete(string id)
|
public async Task<IActionResult> Delete(string id)
|
||||||
{
|
{
|
||||||
|
|
||||||
var fReview = await _applicationContext.UserWriteToMetings.FirstAsync(r => r.Id == 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);
|
_applicationContext.UserWriteToMetings.Remove(fReview);
|
||||||
|
|
||||||
|
|
||||||
@ -487,7 +556,7 @@ public class UserWriteToMetingController : ControllerBase
|
|||||||
[HttpGet("list")]
|
[HttpGet("list")]
|
||||||
public IActionResult GetList(int offset, int limit)
|
public IActionResult GetList(int offset, int limit)
|
||||||
{
|
{
|
||||||
var reviews = _applicationContext.UserWriteToMetings
|
var reviews = _applicationContext.UserWriteToMetings.AsNoTracking()
|
||||||
.Skip(offset)
|
.Skip(offset)
|
||||||
.Take(limit);
|
.Take(limit);
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ public class User : IdentityUser
|
|||||||
public string TelegramBotUrl { get; set; } = null!;
|
public string TelegramBotUrl { get; set; } = null!;
|
||||||
|
|
||||||
public int Level { get; set; }
|
public int Level { get; set; }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UserPost
|
public class UserPost
|
||||||
@ -30,6 +32,23 @@ public class UserPost
|
|||||||
public string TelegramBotUrl { 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 class UserPut
|
||||||
{
|
{
|
||||||
@ -148,7 +167,7 @@ public class Meeting
|
|||||||
|
|
||||||
public string SpeackerImage { get; set; } = null!;
|
public string SpeackerImage { get; set; } = null!;
|
||||||
|
|
||||||
public string Splecializations { get; set; } = null!;
|
public string Splecializations { get; set; } = null!; //speacker specilization
|
||||||
|
|
||||||
|
|
||||||
public string Type { get; set; } = "онлайн/офлайн";
|
public string Type { get; set; } = "онлайн/офлайн";
|
||||||
@ -254,6 +273,18 @@ public class Review
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 class PostReactionDto
|
||||||
{
|
{
|
||||||
@ -293,6 +324,9 @@ public class ApplicationContext : IdentityDbContext<User>
|
|||||||
|
|
||||||
public DbSet<Question> Questions { get; set; }
|
public DbSet<Question> Questions { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public DbSet<Achievment> Achievments { get; set; }
|
||||||
|
|
||||||
public ApplicationContext(DbContextOptions<ApplicationContext> options)
|
public ApplicationContext(DbContextOptions<ApplicationContext> options)
|
||||||
: base(options)
|
: base(options)
|
||||||
{
|
{
|
||||||
@ -318,5 +352,7 @@ public class ApplicationContext : IdentityDbContext<User>
|
|||||||
|
|
||||||
builder.Entity<Meeting>().HasMany<UserWriteToMeting>().WithOne().HasForeignKey(c => c.MeetingId);
|
builder.Entity<Meeting>().HasMany<UserWriteToMeting>().WithOne().HasForeignKey(c => c.MeetingId);
|
||||||
builder.Entity<UserWriteToMeting>().HasOne<User>().WithMany().HasForeignKey(c => c.UserId);
|
builder.Entity<UserWriteToMeting>().HasOne<User>().WithMany().HasForeignKey(c => c.UserId);
|
||||||
|
|
||||||
|
builder.Entity<Achievment>().HasOne<User>().WithMany().HasForeignKey(c => c.UserId);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,9 +12,9 @@ TypeAdapterConfig<PutMeetingDto, Meeting>.NewConfig().Map(d => d.SpeackerImage,
|
|||||||
TypeAdapterConfig<PostMeetingDto, Meeting>.NewConfig().Map(d => d.SpeackerImage, s => s.SpeackerImage.JoinFileNames());
|
TypeAdapterConfig<PostMeetingDto, Meeting>.NewConfig().Map(d => d.SpeackerImage, s => s.SpeackerImage.JoinFileNames());
|
||||||
|
|
||||||
|
|
||||||
TypeAdapterConfig<PostMeetingDto, Meeting>.NewConfig().Map(d => d.Splecializations, s => String.Join(FILES_SEPORATOR_IN_STORE, s.Splecializations));
|
TypeAdapterConfig<PostMeetingDto, Meeting>.NewConfig().Map(d => d.Splecializations, s => String.Join(TOKENS_SEPORATOR, s.Splecializations));
|
||||||
|
|
||||||
TypeAdapterConfig<PutMeetingDto, Meeting>.NewConfig().Map(d => d.Splecializations, s => String.Join(FILES_SEPORATOR_IN_STORE, s.Splecializations));
|
TypeAdapterConfig<PutMeetingDto, Meeting>.NewConfig().Map(d => d.Splecializations, s => String.Join(TOKENS_SEPORATOR, s.Splecializations));
|
||||||
|
|
||||||
|
|
||||||
TypeAdapterConfig<PostMeetingDto, Meeting>.NewConfig().Map(d => d.Time, s => s.Time.ToUniversalTime());
|
TypeAdapterConfig<PostMeetingDto, Meeting>.NewConfig().Map(d => d.Time, s => s.Time.ToUniversalTime());
|
||||||
@ -109,13 +109,24 @@ public class AuthOptions
|
|||||||
|
|
||||||
public static class Consts
|
public static class Consts
|
||||||
{
|
{
|
||||||
public const char FILES_SEPORATOR_IN_STORE = ';';
|
public const char TOKENS_SEPORATOR = ';';
|
||||||
}
|
}
|
||||||
public static class PhileDataHelpers
|
public static class DataHelpers
|
||||||
{
|
{
|
||||||
public static string JoinFileNames(this IEnumerable<IFormFile> files) => files.Select(s => s.FileName).JoinStrings();
|
public static string JoinFileNames(this IEnumerable<IFormFile> files) => files.Select(s => s.FileName).JoinStrings();
|
||||||
|
|
||||||
public static string JoinStrings(this IEnumerable<string> files) => String.Join(FILES_SEPORATOR_IN_STORE, files.Select(s => s));
|
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)
|
public static async Task WriteFileToDirectory(this IFormFile file)
|
||||||
{
|
{
|
||||||
@ -133,4 +144,53 @@ public static class PhileDataHelpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user