Changed how login page works based on user feedback. By default, we have the old login flow when authentication is enabled and in addition, we will auto fill the username based on last login on device. (#621)

This commit is contained in:
Joseph Milazzo 2021-10-02 11:35:38 -07:00 committed by GitHub
parent 34d171f0b4
commit 30a302bf99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 14 deletions

View File

@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc;
namespace API.Controllers
{
[Authorize]
public class UsersController : BaseApiController
{
private readonly IUnitOfWork _unitOfWork;
@ -42,11 +43,15 @@ namespace API.Controllers
[HttpGet("names")]
public async Task<ActionResult<IEnumerable<MemberDto>>> GetUserNames()
{
var setting = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
if (setting.EnableAuthentication)
{
return Unauthorized("This API cannot be used given your server's configuration");
}
var members = await _unitOfWork.UserRepository.GetMembersAsync();
return Ok(members.Select(m => m.Username));
}
[Authorize]
[HttpGet("has-reading-progress")]
public async Task<ActionResult<bool>> HasReadingProgress(int libraryId)
{
@ -55,7 +60,6 @@ namespace API.Controllers
return Ok(await _unitOfWork.AppUserProgressRepository.UserHasProgress(library.Type, userId));
}
[Authorize]
[HttpGet("has-library-access")]
public async Task<ActionResult<bool>> HasLibraryAccess(int libraryId)
{
@ -63,7 +67,6 @@ namespace API.Controllers
return Ok(libs.Any(x => x.Id == libraryId));
}
[Authorize]
[HttpPost("update-preferences")]
public async Task<ActionResult<UserPreferencesDto>> UpdatePreferences(UserPreferencesDto preferencesDto)
{

View File

@ -16,6 +16,7 @@ export class AccountService implements OnDestroy {
baseUrl = environment.apiUrl;
userKey = 'kavita-user';
public lastLoginKey = 'kavita-lastlogin';
currentUser: User | undefined;
// Stores values, when someone subscribes gives (1) of last values seen.
@ -70,6 +71,7 @@ export class AccountService implements OnDestroy {
});
localStorage.setItem(this.userKey, JSON.stringify(user));
localStorage.setItem(this.lastLoginKey, user.username);
}
this.currentUserSource.next(user);

View File

@ -19,9 +19,9 @@
</span>
<div class="card-text" #collapse="ngbCollapse" [(ngbCollapse)]="isCollapsed[member]" (keyup.enter)="$event.stopPropagation()">
<div class="form-group" style="display: none;">
<div class="form-group" [ngStyle]="authDisabled ? {display: 'none'} : {}">
<label for="username--{{member}}">Username</label>
<input class="form-control" formControlName="username" id="username--{{member}}" type="text" [readonly]="true">
<input class="form-control" formControlName="username" id="username--{{member}}" type="text" [readonly]="authDisabled">
</div>
<div class="form-group">

View File

@ -46,24 +46,43 @@ export class UserLoginComponent implements OnInit {
this.authDisabled = enabled + '' === 'false';
if (this.authDisabled) {
this.loginForm.get('password')?.setValidators([]);
// This API is only useable on disabled authentication
this.memberService.getMemberNames().pipe(take(1)).subscribe(members => {
this.memberNames = members;
const isOnlyOne = this.memberNames.length === 1;
this.memberNames.forEach(name => this.isCollapsed[name] = !isOnlyOne);
this.firstTimeFlow = members.length === 0;
});
} else {
this.memberService.adminExists().pipe(take(1)).subscribe(adminExists => {
this.firstTimeFlow = !adminExists;
this.setupAuthenticatedLoginFlow();
});
}
});
this.memberService.getMemberNames().pipe(take(1)).subscribe(members => {
this.memberNames = members;
const isOnlyOne = this.memberNames.length === 1;
this.memberNames.forEach(name => this.isCollapsed[name] = !isOnlyOne);
this.firstTimeFlow = members.length === 0;
}
});
setupAuthenticatedLoginFlow() {
if (this.memberNames.indexOf(' Login ') >= 0) { return; }
this.memberNames.push(' Login ');
this.memberNames.forEach(name => this.isCollapsed[name] = false);
const lastLogin = localStorage.getItem(this.accountService.lastLoginKey);
if (lastLogin != undefined && lastLogin != null && lastLogin != '') {
this.loginForm.get('username')?.setValue(lastLogin);
}
}
onAdminCreated(user: User | null) {
if (user != null) {
this.firstTimeFlow = false;
this.isCollapsed[user.username] = true;
this.select(user.username);
this.memberNames.push(user.username);
if (this.authDisabled) {
this.isCollapsed[user.username] = true;
this.select(user.username);
this.memberNames.push(user.username);
}
} else {
this.toastr.error('There was an issue creating the new user. Please refresh and try again.');
}
@ -95,6 +114,10 @@ export class UserLoginComponent implements OnInit {
}
select(member: string) {
// This is a special case
if (member === ' Login ' && !this.authDisabled) {
return;
}
this.loginForm.get('username')?.setValue(member);