Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Random Bugs #2531

Merged
merged 13 commits into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/DISCUSSION_TEMPLATE/ideas.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
title: "[Kavita] Idea Submission"
labels: ["Idea Submission"]
body:
- type: markdown
attributes:
value: |
## 🌟 Idea Submission for Kavita 🌟

This is a template for submitting your ideas to enhance Kavita. Please fill out the details below, and let's make Kavita even better together!

- type: textarea
id: idea-description
attributes:
label: Idea Description
description: "Describe your idea in detail."
value: |
[Include a brief overview of your idea]

- type: markdown
attributes:
value: |
**Why I Think This Is Important:**

[Provide context on why you believe this idea is valuable or necessary for Kavita users]

- type: markdown
attributes:
value: |
**How You Can Contribute:**

1. **Upvote if You Agree:**
- If you resonate with my idea, please upvote it! This helps us gauge community interest.

2. **Leave Your Thoughts:**
- Feel free to leave comments with your opinions, suggestions, or even constructive critiques.

Let's work together to shape the future of Kavita! 🌟

- type: input
id: duration-of-use
attributes:
label: Duration of Using Kavita
description: "How long have you been using Kavita?"
validations:
required: true

- type: dropdown
id: idea-category
attributes:
label: Idea Category
options:
- Feature Enhancement
- User Experience
- Performance Improvement
description: "Select the category that best fits your idea."
validations:
required: true

- type: checkboxes
attributes:
label: Agreement
options:
- label: "I agree that this is solely for submitting ideas, and I will search for existing ideas before posting."
required: true

- type: markdown
attributes:
value: |
### Thank you for contributing to Kavita's future! 🚀
34 changes: 25 additions & 9 deletions API/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@
{
user = await _userManager.Users
.Include(u => u.UserPreferences)
.SingleOrDefaultAsync(x => x.NormalizedUserName == loginDto.Username.ToUpper());
.SingleOrDefaultAsync(x => x.NormalizedUserName == loginDto.Username.ToUpperInvariant());
}

_logger.LogInformation("{UserName} attempting to login from {IpAddress}", loginDto.Username, HttpContext.Connection.RemoteIpAddress?.ToString());
Expand Down Expand Up @@ -390,7 +390,8 @@
return Ok(new InviteUserResponse
{
EmailLink = string.Empty,
EmailSent = false
EmailSent = false,
InvalidEmail = true,
});
}

Expand Down Expand Up @@ -484,6 +485,7 @@
var errors = await _accountService.ValidateUsername(dto.Username);
if (errors.Any()) return BadRequest(await _localizationService.Translate(User.GetUserId(), "username-taken"));
user.UserName = dto.Username;
await _userManager.UpdateNormalizedUserNameAsync(user);
_unitOfWork.UserRepository.Update(user);
}

Expand Down Expand Up @@ -689,7 +691,8 @@
return Ok(new InviteUserResponse
{
EmailLink = emailLink,
EmailSent = false
EmailSent = false,
InvalidEmail = true
});
}

Expand Down Expand Up @@ -974,13 +977,12 @@

var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var emailLink = await _accountService.GenerateEmailLink(Request, token, "confirm-email", user.Email);
_logger.LogCritical("[Email Migration]: Email Link: {Link}", emailLink);
_logger.LogCritical("[Email Migration]: Token {UserName}: {Token}", user.UserName, token);
_logger.LogCritical("[Email Migration]: Email Link for {UserName}: {Link}", user.UserName, emailLink);
Dismissed Show dismissed Hide dismissed
Dismissed Show dismissed Hide dismissed

if (!_emailService.IsValidEmail(user.Email))
{
_logger.LogCritical("[Email Migration]: User is trying to resend an invite flow, but their email ({Email}) isn't valid. No email will be send", user.Email);
return Ok(await _localizationService.Translate(user.Id, "invalid-email"));
_logger.LogCritical("[Email Migration]: User {UserName} is trying to resend an invite flow, but their email ({Email}) isn't valid. No email will be send", user.UserName, user.Email);
return BadRequest(await _localizationService.Translate(user.Id, "invalid-email"));
}

if (await _accountService.CheckIfAccessible(Request))
Expand All @@ -1003,7 +1005,7 @@
return Ok(emailLink);
}

return Ok(await _localizationService.Translate(user.Id, "not-accessible"));
return BadRequest(await _localizationService.Translate(user.Id, "not-accessible"));
}

/// <summary>
Expand Down Expand Up @@ -1102,12 +1104,26 @@
baseUrl = baseUrl.Replace("//", "/");
}

if (baseUrl.StartsWith("/"))
if (baseUrl.StartsWith('/'))
{
baseUrl = baseUrl.Substring(1, baseUrl.Length - 1);
}
}
return Ok(origin + "/" + baseUrl + "api/opds/" + user!.ApiKey);
}


/// <summary>
/// Is the user's current email valid or not
/// </summary>
/// <returns></returns>
[HttpGet("is-email-valid")]
public async Task<ActionResult<bool>> IsEmailValid()
{
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId());
if (user == null) return Unauthorized();
if (string.IsNullOrEmpty(user.Email)) return Ok(false);

return Ok(_emailService.IsValidEmail(user.Email));
}
}
4 changes: 4 additions & 0 deletions API/DTOs/Account/InviteUserResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ public class InviteUserResponse
/// Was an email sent (ie is this server accessible)
/// </summary>
public bool EmailSent { get; set; } = default!;
/// <summary>
/// When a user has an invalid email and is attempting to perform a flow.
/// </summary>
public bool InvalidEmail { get; set; } = false;
}
14 changes: 0 additions & 14 deletions API/DTOs/Account/UpdateEmailResponse.cs

This file was deleted.

1 change: 1 addition & 0 deletions API/Helpers/Builders/VolumeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public VolumeBuilder(string volumeNumber)
_volume = new Volume()
{
Name = volumeNumber,
// TODO / BUG: Try to use float based Number which will allow Epub's with < 1 volumes to show in series detail
Number = (int) Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(volumeNumber),
Chapters = new List<Chapter>()
};
Expand Down
26 changes: 25 additions & 1 deletion API/Logging/LogLevelOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Serilog;
using System.Text.RegularExpressions;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting.Display;
Expand Down Expand Up @@ -49,6 +50,7 @@ public static LoggerConfiguration CreateConfig(LoggerConfiguration configuration
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Error)
.Enrich.FromLogContext()
.Enrich.WithThreadId()
.Enrich.With(new ApiKeyEnricher())
.WriteTo.Console(new MessageTemplateTextFormatter(outputTemplate))
.WriteTo.File(LogFile,
shared: true,
Expand All @@ -74,6 +76,7 @@ private static bool ShouldIncludeLogStatement(LogEvent e)
if (e.Properties.ContainsKey("Path") && e.Properties["Path"].ToString().Replace("\"", string.Empty) == "/api/health") return false;
if (e.Properties.ContainsKey("Path") && e.Properties["Path"].ToString().Replace("\"", string.Empty) == "/hubs/messages") return false;
}

return true;
}

Expand Down Expand Up @@ -115,3 +118,24 @@ public static void SwitchLogLevel(string level)
}

}

public partial class ApiKeyEnricher : ILogEventEnricher
{
public void Enrich(LogEvent e, ILogEventPropertyFactory propertyFactory)
{
var isRequestLoggingMiddleware = e.Properties.ContainsKey("SourceContext") &&
e.Properties["SourceContext"].ToString().Replace("\"", string.Empty) ==
"Serilog.AspNetCore.RequestLoggingMiddleware";
if (!isRequestLoggingMiddleware) return;
if (!e.Properties.ContainsKey("RequestPath") ||
!e.Properties["RequestPath"].ToString().Contains("apiKey=")) return;

// Check if the log message contains "apiKey=" and censor it
var censoredMessage = MyRegex().Replace(e.Properties["RequestPath"].ToString(), "apiKey=******REDACTED******");
var enrichedProperty = propertyFactory.CreateProperty("RequestPath", censoredMessage);
e.AddOrUpdateProperty(enrichedProperty);
}

[GeneratedRegex(@"\bapiKey=[^&\s]+\b")]
private static partial Regex MyRegex();
}
101 changes: 0 additions & 101 deletions API/Middleware/CustomAuthHeaderMiddleware.cs

This file was deleted.

2 changes: 1 addition & 1 deletion API/Services/AccountService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public async Task<string> GenerateEmailLink(HttpRequest request, string token, s
basePart = serverSettings.HostName;
if (!serverSettings.BaseUrl.Equals(Configuration.DefaultBaseUrl))
{
var removeCount = serverSettings.BaseUrl.EndsWith("/") ? 2 : 1;
var removeCount = serverSettings.BaseUrl.EndsWith('/') ? 1 : 0;
basePart += serverSettings.BaseUrl.Substring(0, serverSettings.BaseUrl.Length - removeCount);
}
}
Expand Down
1 change: 0 additions & 1 deletion API/Services/BookService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,6 @@ await _mediaErrorService.ReportMediaIssueAsync(book.FilePath, MediaErrorProducer
ExtractSortTitle(metadataItem, epubBook, info);
}


break;
}
}
Expand Down
5 changes: 0 additions & 5 deletions API/Services/Tasks/Scanner/ProcessSeries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,6 @@ public void UpdateSeriesMetadata(Series series, Library library)

public void UpdateVolumes(Series series, IList<ParserInfo> parsedInfos, bool forceUpdate = false)
{
var startingVolumeCount = series.Volumes.Count;
// Add new volumes and update chapters per volume
var distinctVolumes = parsedInfos.DistinctVolumes();
_logger.LogDebug("[ScannerService] Updating {DistinctVolumes} volumes on {SeriesName}", distinctVolumes.Count, series.Name);
Expand Down Expand Up @@ -582,10 +581,6 @@ public void UpdateVolumes(Series series, IList<ParserInfo> parsedInfos, bool for

series.Volumes = nonDeletedVolumes;
}

// DO I need this anymore?
_logger.LogDebug("[ScannerService] Updated {SeriesName} volumes from count of {StartingVolumeCount} to {VolumeCount}",
series.Name, startingVolumeCount, series.Volumes.Count);
}

public void UpdateChapters(Series series, Volume volume, IList<ParserInfo> parsedInfos, bool forceUpdate = false)
Expand Down
1 change: 0 additions & 1 deletion API/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,6 @@ public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJo

app.UseMiddleware<ExceptionMiddleware>();
app.UseMiddleware<SecurityEventMiddleware>();
app.UseMiddleware<CustomAuthHeaderMiddleware>();


if (env.IsDevelopment())
Expand Down
6 changes: 5 additions & 1 deletion UI/Web/src/app/_models/auth/invite-user-response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ export interface InviteUserResponse {
* If an email was sent to the invited user
*/
emailSent: boolean;
}
/**
* When a user has an invalid email and is attempting to perform a flow.
*/
invalidEmail: boolean;
}
Loading
Loading