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

Feature/no ref/change password redirection #1290

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
567 changes: 286 additions & 281 deletions shesha-core/src/Shesha.Application/Authorization/TokenAuthController.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public class UserLoginInfoDto : EntityDto<long>
//public TypeOfAccount? TypeOfAccount { get; set; }
public string HomeUrl { get; set; }
public bool IsSelfServiceUser { get; set; }

public bool ShouldChangePassword { get; set; }
public string PasswordChangeUrl { get; set; }
public List<string> GrantedPermissions { get; set; } = new List<string>();
}
}
218 changes: 112 additions & 106 deletions shesha-core/src/Shesha.Application/Sessions/SessionAppService.cs
Original file line number Diff line number Diff line change
@@ -1,114 +1,120 @@
using Abp.Auditing;
using Abp.Domain.Repositories;
using Microsoft.AspNetCore.Mvc;
using Shesha.Authorization;
using Shesha.Domain;
using Abp.Auditing;
using Abp.Domain.Repositories;
using Microsoft.AspNetCore.Mvc;
using Shesha.Authorization;
using Shesha.Configuration;
using Shesha.Domain;
using Shesha.Extensions;
using Shesha.Sessions.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Shesha.Sessions
{
public class SessionAppService : SheshaAppServiceBase, ISessionAppService
{
private readonly IRepository<ShaRoleAppointedPerson, Guid> _roleAppointmentRepository;
private readonly IShaPermissionChecker _permissionChecker;

public IHomePageRouter HomePageRouter { get; set; } = new NullHomePageRouter();

public SessionAppService(IRepository<ShaRoleAppointedPerson, Guid> roleAppointmentRepository, IShaPermissionChecker permissionChecker)
{
_roleAppointmentRepository = roleAppointmentRepository;
_permissionChecker = permissionChecker;
}

[Obsolete]
using Shesha.Sessions.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Shesha.Sessions
{
public class SessionAppService : SheshaAppServiceBase, ISessionAppService
{
private readonly IRepository<ShaRoleAppointedPerson, Guid> _roleAppointmentRepository;
private readonly IShaPermissionChecker _permissionChecker;
private readonly IAuthenticationSettings _authSetting;

public IHomePageRouter HomePageRouter { get; set; } = new NullHomePageRouter();

public SessionAppService(IRepository<ShaRoleAppointedPerson, Guid> roleAppointmentRepository, IShaPermissionChecker permissionChecker,
IAuthenticationSettings authSetting)
{
_roleAppointmentRepository = roleAppointmentRepository;
_permissionChecker = permissionChecker;
_authSetting = authSetting;
}

[Obsolete]
public async Task<GetCurrentLoginInfoOutput> GetCurrentLoginInformations()
{
return await GetCurrentLoginInfo();
}

public async Task<GetCurrentLoginInfoOutput> GetCurrentLoginInfo()
{
var output = new GetCurrentLoginInfoOutput { };

if (AbpSession.TenantId.HasValue)
{
output.Tenant = ObjectMapper.Map<TenantLoginInfoDto>(await GetCurrentTenantAsync());
}

if (AbpSession.UserId.HasValue)
{
var user = await GetCurrentUserAsync();

string homeUrl = await HomePageRouter.GetHomePageUrlAsync(user);

output.User = new UserLoginInfoDto
{
AccountFound = true,
UserName = user.UserName,
FirstName = user.Name,
LastName = user.Surname,
FullName = user.FullName,
Email = user.EmailAddress,
MobileNumber = user.PhoneNumber,
GrantedPermissions = await GetGrantedPermissions(),
HomeUrl = homeUrl
};
}

return output;
}

private async Task<List<string>> GetGrantedPermissions()
{
var grantedPermissions = new List<string>();

if (AbpSession.UserId.HasValue)
{
return await GetCurrentLoginInfo();
}

public async Task<GetCurrentLoginInfoOutput> GetCurrentLoginInfo()
{
var output = new GetCurrentLoginInfoOutput { };

if (AbpSession.TenantId.HasValue)
{
output.Tenant = ObjectMapper.Map<TenantLoginInfoDto>(await GetCurrentTenantAsync());
}

if (AbpSession.UserId.HasValue)
{
var user = await GetCurrentUserAsync();

string homeUrl = await HomePageRouter.GetHomePageUrlAsync(user);

output.User = new UserLoginInfoDto
{
AccountFound = true,
UserName = user.UserName,
FirstName = user.Name,
LastName = user.Surname,
FullName = user.FullName,
Email = user.EmailAddress,
MobileNumber = user.PhoneNumber,
GrantedPermissions = await GetGrantedPermissions(),
HomeUrl = homeUrl,
ShouldChangePassword = user.ChangePasswordOnNextLogin,
PasswordChangeUrl = user.ChangePasswordOnNextLogin ? await _authSetting.PasswordChangeUrl.GetValueAsync() : null
};
}

return output;
}

private async Task<List<string>> GetGrantedPermissions()
{
var grantedPermissions = new List<string>();

if (AbpSession.UserId.HasValue)
{
var allPermissionNames = PermissionManager.GetAllPermissions(false).Select(p => p.Name).ToList();

foreach (var permissionName in allPermissionNames)
{
if (await PermissionChecker.IsGrantedAsync(permissionName))
grantedPermissions.Add(permissionName);
}
}

return grantedPermissions;
foreach (var permissionName in allPermissionNames)
{
if (await PermissionChecker.IsGrantedAsync(permissionName))
grantedPermissions.Add(permissionName);
}
}
return grantedPermissions;
}


/// <summary>
/// I am using this method to get user roles and it is being used on login of a user and also when changing work Order Type, Please contact me(Moses) before removing it
/// </summary>
/// <returns></returns>
[DisableAuditing]
public async Task<List<string>> GetGrantedShaRoles()
{
var currentUser = AbpSession.UserId.HasValue
? await GetCurrentPersonAsync()
: null;
if (currentUser == null)
return new List<string>();
var roles = await _roleAppointmentRepository.GetAll()
.Where(a => a.Person == currentUser)
.Select(a => a.Role.Name)
.Distinct()
.ToListAsync();
return roles;
}

/// <summary>
/// Clears permissions cache
/// </summary>
[HttpPost]
public async Task ClearPermissionsCache()
{
await _permissionChecker.ClearPermissionsCacheAsync();
}
}
}
/// <summary>
/// I am using this method to get user roles and it is being used on login of a user and also when changing work Order Type, Please contact me(Moses) before removing it
/// </summary>
/// <returns></returns>
[DisableAuditing]
public async Task<List<string>> GetGrantedShaRoles()
{
var currentUser = AbpSession.UserId.HasValue
? await GetCurrentPersonAsync()
: null;
if (currentUser == null)
return new List<string>();
var roles = await _roleAppointmentRepository.GetAll()
.Where(a => a.Person == currentUser)
.Select(a => a.Role.Name)
.Distinct()
.ToListAsync();
return roles;
}
/// <summary>
/// Clears permissions cache
/// </summary>
[HttpPost]
public async Task ClearPermissionsCache()
{
await _permissionChecker.ClearPermissionsCacheAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,12 @@ public interface IAuthenticationSettings: ISettingAccessors
[Display(Name = "Num questions allowed")]
[Setting(SheshaSettingNames.Security.ResetPasswordWithSecurityQuestionsNumQuestionsAllowed)]
ISettingAccessor<int> ResetPasswordViaSecurityQuestionsNumQuestionsAllowed { get; }

/// <summary>
/// When you require users to change their passwords, this is the URL they will be redirected to
/// </summary>
[Display(Name = "Password change URL")]
[Setting(SheshaSettingNames.Security.PasswordChangeUrl)]
ISettingAccessor<string> PasswordChangeUrl { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public static class Security
public const string MobileLoginPinLifetime = "Shesha.Security.MobileLoginPinLifetime";
public const string ResetPasswordWithSecurityQuestionsIsSupported = "Shesha.Security.ResetPasswordWithSecurityQuestionsIsSupported";
public const string ResetPasswordWithSecurityQuestionsNumQuestionsAllowed = "Shesha.Security.ResetPasswordWithSecurityQuestionsNumQuestionsAllowed";

public const string PasswordChangeUrl = "Shesha.Security.PasswordChangeUrl";
}

public static class Sms
Expand Down
1 change: 1 addition & 0 deletions shesha-core/src/Shesha.Framework/SheshaFrameworkModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public override void Initialize()

s.AutoLogoffTimeout.WithDefaultValue(0);
s.ResetPasswordViaSecurityQuestionsNumQuestionsAllowed.WithDefaultValue(3);
s.PasswordChangeUrl.WithDefaultValue("/account/change-password");
});
IocManager.RegisterSettingAccessor<IPasswordComplexitySettings>(s => {
s.RequiredLength.WithDefaultValue(3);
Expand Down
2 changes: 1 addition & 1 deletion shesha-core/src/Shesha.Web.Host/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"ConnectionStrings": {
"Default": "Data Source=.; Initial Catalog=function-shesha-test;Integrated Security=SSPI"
"Default": "Data Source=.; Initial Catalog=function-shesha-test;Integrated Security=SSPI;TrustServerCertificate=true"
},
"App": {
"ServerRootAddress": "http://sheshacore-demo.boxfusion.co.za",
Expand Down
104 changes: 53 additions & 51 deletions shesha-reactjs/src/apis/session.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,53 @@
import { IAjaxResponse, IAjaxResponseBase } from '@/interfaces/ajaxResponse';
import * as RestfulShesha from '@/utils/fetchers';

export interface UserLoginInfoDto {
id?: number;
accountFound?: boolean;
userName?: string | null;
firstName?: string | null;
lastName?: string | null;
fullName?: string | null;
picture?: string | null;
email?: string | null;
mobileNumber?: string | null;
hasRegistered?: boolean;
loginProvider?: string | null;
homeUrl?: string | null;
isSelfServiceUser?: boolean;
grantedPermissions?: string[] | null;
}
export interface ApplicationInfoDto {
version?: string | null;
releaseDate?: string;
features?: {
[key: string]: boolean;
} | null;
}

export interface TenantLoginInfoDto {
id?: number;
tenancyName?: string | null;
name?: string | null;
}
export interface GetCurrentLoginInfoOutput {
application?: ApplicationInfoDto;
user?: UserLoginInfoDto;
tenant?: TenantLoginInfoDto;
}

export interface GetCurrentLoginInfoOutputAjaxResponse extends IAjaxResponse<GetCurrentLoginInfoOutput> {}

export type sessionGetCurrentLoginInfoProps = Omit<
RestfulShesha.GetProps<GetCurrentLoginInfoOutputAjaxResponse, IAjaxResponseBase, void, void>,
'queryParams'
>;

export const sessionGetCurrentLoginInfo = (props: sessionGetCurrentLoginInfoProps) =>
RestfulShesha.get<GetCurrentLoginInfoOutputAjaxResponse, IAjaxResponseBase, void, void>(
`/api/services/app/Session/GetCurrentLoginInfo`,
undefined,
props
);
import { IAjaxResponse, IAjaxResponseBase } from '@/interfaces/ajaxResponse';
import * as RestfulShesha from '@/utils/fetchers';

export interface UserLoginInfoDto {
id?: number;
accountFound?: boolean;
userName?: string | null;
firstName?: string | null;
lastName?: string | null;
fullName?: string | null;
picture?: string | null;
email?: string | null;
mobileNumber?: string | null;
hasRegistered?: boolean;
loginProvider?: string | null;
homeUrl?: string | null;
isSelfServiceUser?: boolean;
shouldChangePassword?: boolean;
passwordChangeUrl?: string | null;
grantedPermissions?: string[] | null;
}
export interface ApplicationInfoDto {
version?: string | null;
releaseDate?: string;
features?: {
[key: string]: boolean;
} | null;
}

export interface TenantLoginInfoDto {
id?: number;
tenancyName?: string | null;
name?: string | null;
}
export interface GetCurrentLoginInfoOutput {
application?: ApplicationInfoDto;
user?: UserLoginInfoDto;
tenant?: TenantLoginInfoDto;
}

export interface GetCurrentLoginInfoOutputAjaxResponse extends IAjaxResponse<GetCurrentLoginInfoOutput> {}

export type sessionGetCurrentLoginInfoProps = Omit<
RestfulShesha.GetProps<GetCurrentLoginInfoOutputAjaxResponse, IAjaxResponseBase, void, void>,
'queryParams'
>;

export const sessionGetCurrentLoginInfo = (props: sessionGetCurrentLoginInfoProps) =>
RestfulShesha.get<GetCurrentLoginInfoOutputAjaxResponse, IAjaxResponseBase, void, void>(
`/api/services/app/Session/GetCurrentLoginInfo`,
undefined,
props
);
Loading