сделал авторизация доабвил оптимизацию
All checks were successful
Create and publish a Docker image / Publish image (push) Successful in 1m26s
Create and publish a Docker image / Deploy image (push) Successful in 38s

This commit is contained in:
Vitalick Kovalenko 2023-12-23 23:34:14 +03:00
parent 6a32bc4fa9
commit b4b5bfc1ed
3 changed files with 197 additions and 32 deletions

View File

@ -6,7 +6,9 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.IdentityModel.Tokens;
using static Consts;
namespace CyberBoom.Controllers;
@ -14,10 +16,6 @@ namespace CyberBoom.Controllers;
[Route("/api/[controller]")]
public class UsersController : ControllerBase
{
private readonly ApplicationContext _applicationContext;
private readonly UserManager<User> _userManager;
@ -131,6 +129,25 @@ public class UsersController : ControllerBase
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")]
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);
@ -272,7 +289,7 @@ public class ReviewsController : ControllerBase
[HttpGet("list")]
public IActionResult GetList(int offset, int limit)
{
var reviews = _applicationContext.Reviews
var reviews = _applicationContext.Reviews.AsNoTracking()
.Include(c => c.User)
.Skip(offset)
.Take(limit);
@ -341,7 +358,7 @@ public class QuestionsController : ControllerBase
[HttpGet("list")]
public IActionResult GetList(int offset, int limit)
{
var questions = _applicationContext.Questions
var questions = _applicationContext.Questions.AsNoTracking()
.Include(c => c.User)
.Skip(offset)
.Take(limit);
@ -398,32 +415,23 @@ public class ReactionsController : ControllerBase
[HttpGet]
public async Task<IActionResult> Get(string id)
{
var review = await _applicationContext.Reviews
var reaction = await _applicationContext.Reactions
.FirstAsync(s => s.Id == id);
var user = await _applicationContext.Users.FirstAsync(s => s.Id == review.UserId);
return Ok(new {
review,
user
});
return Ok(reaction);
}
[HttpGet("list")]
public IActionResult GetList(int offset, int limit)
{
var reviews = _applicationContext.Reviews
var reactions = _applicationContext.Reactions.AsNoTracking()
.Skip(offset)
.Take(limit);
var users = _applicationContext.Users.Where(u => reviews.Select(u => u.UserId).Contains(u.Id));
return Ok(
reviews.Select(s => new {
review = s,
user = users.First(u => u.Id == s.UserId)
})
);
return Ok(reactions);
}
}
@ -449,22 +457,83 @@ public class UserWriteToMetingController : ControllerBase
{
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
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);
@ -487,7 +556,7 @@ public class UserWriteToMetingController : ControllerBase
[HttpGet("list")]
public IActionResult GetList(int offset, int limit)
{
var reviews = _applicationContext.UserWriteToMetings
var reviews = _applicationContext.UserWriteToMetings.AsNoTracking()
.Skip(offset)
.Take(limit);

View File

@ -15,6 +15,8 @@ public class User : IdentityUser
public string TelegramBotUrl { get; set; } = null!;
public int Level { get; set; }
}
public class UserPost
@ -30,6 +32,23 @@ public class UserPost
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
{
@ -148,7 +167,7 @@ public class Meeting
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; } = "онлайн/офлайн";
@ -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
{
@ -293,6 +324,9 @@ public class ApplicationContext : IdentityDbContext<User>
public DbSet<Question> Questions { get; set; }
public DbSet<Achievment> Achievments { get; set; }
public ApplicationContext(DbContextOptions<ApplicationContext> options)
: base(options)
{
@ -318,5 +352,7 @@ public class ApplicationContext : IdentityDbContext<User>
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);
}
}

View File

@ -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.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());
@ -109,13 +109,24 @@ public class AuthOptions
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 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)
{
@ -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;
}
}