更新
This commit is contained in:
@@ -9,10 +9,10 @@ public sealed class PasswordAccessService : IPasswordAccessService
|
|||||||
private const int ExpirationReminderDays = 3;
|
private const int ExpirationReminderDays = 3;
|
||||||
private const string SettingsDirectoryName = "Cardiopulmonarybypasssystems";
|
private const string SettingsDirectoryName = "Cardiopulmonarybypasssystems";
|
||||||
private const string StatusFileName = "password-access.json";
|
private const string StatusFileName = "password-access.json";
|
||||||
public const string FirstStagePassword = "152026";
|
public const string FirstStagePassword = "152026001";
|
||||||
public const string SecondStagePassword = "302026";
|
public const string SecondStagePassword = "302026002";
|
||||||
private const int FirstStageDays = 15;
|
private const int InitialAccessDays = 20;
|
||||||
private const int SecondStageDays = 30;
|
private const int ExtendedAccessDays = 30;
|
||||||
|
|
||||||
private static readonly string StatusFilePath = Path.Combine(
|
private static readonly string StatusFilePath = Path.Combine(
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||||
@@ -21,14 +21,14 @@ public sealed class PasswordAccessService : IPasswordAccessService
|
|||||||
|
|
||||||
public PasswordAccessStatus GetStatus()
|
public PasswordAccessStatus GetStatus()
|
||||||
{
|
{
|
||||||
var state = LoadState();
|
var state = LoadOrCreateState();
|
||||||
return BuildStatus(state, persistState: true);
|
return BuildStatus(state, persistState: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryUnlock(string password, out PasswordAccessStatus status, out string message)
|
public bool TryUnlock(string password, out PasswordAccessStatus status, out string message)
|
||||||
{
|
{
|
||||||
var normalizedPassword = password?.Trim() ?? string.Empty;
|
var normalizedPassword = password?.Trim() ?? string.Empty;
|
||||||
var state = LoadState();
|
var state = LoadOrCreateState();
|
||||||
var currentStatus = BuildStatus(state, persistState: true);
|
var currentStatus = BuildStatus(state, persistState: true);
|
||||||
|
|
||||||
if (currentStatus.IsPermanent)
|
if (currentStatus.IsPermanent)
|
||||||
@@ -38,82 +38,81 @@ public sealed class PasswordAccessService : IPasswordAccessService
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentStatus.Stage == 1 && currentStatus.CanLaunch)
|
if (currentStatus.CanLaunch)
|
||||||
{
|
{
|
||||||
status = currentStatus;
|
status = currentStatus;
|
||||||
message = "第 1 阶段仍在有效期内,无需再次输入密码。";
|
message = currentStatus.ShouldPromptAtStartup
|
||||||
return true;
|
? $"当前仍在有效期内,可直接进入系统;满 {GetStageDays(currentStatus.Stage)} 天后再输入密码。"
|
||||||
|
: $"{GetStageName(currentStatus.Stage)}仍在有效期内,无需再次输入密码。";
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentStatus.Stage == 2 && currentStatus.CanLaunch)
|
var expectedPassword = currentStatus.Stage switch
|
||||||
{
|
{
|
||||||
status = currentStatus;
|
0 => FirstStagePassword,
|
||||||
message = "第 2 阶段仍在有效期内,无需再次输入密码。";
|
1 => SecondStagePassword,
|
||||||
return true;
|
_ => string.Empty
|
||||||
}
|
|
||||||
|
|
||||||
var nextStage = currentStatus.Stage switch
|
|
||||||
{
|
|
||||||
<= 0 => 1,
|
|
||||||
1 => 2,
|
|
||||||
_ => 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (nextStage == 0)
|
|
||||||
{
|
|
||||||
status = BuildStatus(state, persistState: true);
|
|
||||||
message = "当前版本已转为永久有效,不再需要密码。";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectedPassword = nextStage == 1 ? FirstStagePassword : SecondStagePassword;
|
|
||||||
if (!string.Equals(normalizedPassword, expectedPassword, StringComparison.Ordinal))
|
if (!string.Equals(normalizedPassword, expectedPassword, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
status = currentStatus;
|
status = currentStatus;
|
||||||
message = $"密码错误,请输入第 {nextStage} 次时效密码。";
|
message = currentStatus.Stage switch
|
||||||
|
{
|
||||||
|
0 => "密码错误,请输入第 1 次时效密码。",
|
||||||
|
1 => "密码错误,请输入第 2 次时效密码。",
|
||||||
|
_ => "密码错误。"
|
||||||
|
};
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
var expiresAt = now.AddDays(nextStage == 1 ? FirstStageDays : SecondStageDays);
|
|
||||||
|
if (currentStatus.Stage == 1)
|
||||||
|
{
|
||||||
|
var permanentState = new PasswordAccessState
|
||||||
|
{
|
||||||
|
Stage = 2,
|
||||||
|
ActivatedAt = state?.ActivatedAt ?? now,
|
||||||
|
ExpiresAt = null
|
||||||
|
};
|
||||||
|
|
||||||
|
SaveState(permanentState);
|
||||||
|
status = BuildStatus(permanentState, persistState: false);
|
||||||
|
message = "第 2 次密码验证通过,系统已永久有效。";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var expiresAt = now.AddDays(ExtendedAccessDays);
|
||||||
var nextState = new PasswordAccessState
|
var nextState = new PasswordAccessState
|
||||||
{
|
{
|
||||||
Stage = nextStage,
|
Stage = 1,
|
||||||
ActivatedAt = now,
|
ActivatedAt = now,
|
||||||
ExpiresAt = expiresAt
|
ExpiresAt = expiresAt
|
||||||
};
|
};
|
||||||
|
|
||||||
SaveState(nextState);
|
SaveState(nextState);
|
||||||
status = BuildStatus(nextState, persistState: false);
|
status = BuildStatus(nextState, persistState: false);
|
||||||
message = nextStage == 1
|
message = $"第 1 次密码验证通过,已继续开放 {ExtendedAccessDays} 天,有效期至 {expiresAt:yyyy-MM-dd HH:mm}。";
|
||||||
? $"第 1 次时效已生效,有效期至 {expiresAt:yyyy-MM-dd HH:mm}。"
|
|
||||||
: $"第 2 次时效已生效,有效期至 {expiresAt:yyyy-MM-dd HH:mm};到期后自动转为永久有效。";
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PasswordAccessStatus BuildStatus(PasswordAccessState? state, bool persistState)
|
private static PasswordAccessStatus BuildStatus(PasswordAccessState? state, bool persistState)
|
||||||
{
|
{
|
||||||
if (state is null || state.Stage <= 0)
|
if (state is null)
|
||||||
{
|
{
|
||||||
return new PasswordAccessStatus
|
state = CreateInitialState();
|
||||||
|
if (persistState)
|
||||||
{
|
{
|
||||||
Stage = 0,
|
SaveState(state);
|
||||||
CanLaunch = false,
|
}
|
||||||
IsPermanent = false,
|
|
||||||
ShouldPromptAtStartup = true,
|
|
||||||
CanSubmitPassword = true,
|
|
||||||
StageText = "当前阶段:未开始",
|
|
||||||
StatusTitle = "需要输入第 1 次时效密码",
|
|
||||||
StatusDetail = $"输入 15 天密码后进入系统。",
|
|
||||||
RemainingDays = 0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.Stage >= 3)
|
if (state.Stage >= 2)
|
||||||
{
|
{
|
||||||
return new PasswordAccessStatus
|
return new PasswordAccessStatus
|
||||||
{
|
{
|
||||||
Stage = 3,
|
Stage = 2,
|
||||||
CanLaunch = true,
|
CanLaunch = true,
|
||||||
IsPermanent = true,
|
IsPermanent = true,
|
||||||
ShouldPromptAtStartup = false,
|
ShouldPromptAtStartup = false,
|
||||||
@@ -129,63 +128,96 @@ public sealed class PasswordAccessService : IPasswordAccessService
|
|||||||
if (state.ExpiresAt > now)
|
if (state.ExpiresAt > now)
|
||||||
{
|
{
|
||||||
var remainingDays = Math.Max(1, (int)Math.Ceiling((state.ExpiresAt.Value - now).TotalDays));
|
var remainingDays = Math.Max(1, (int)Math.Ceiling((state.ExpiresAt.Value - now).TotalDays));
|
||||||
|
var isReminderWindow = remainingDays <= ExpirationReminderDays;
|
||||||
|
var isInitialStage = state.Stage == 0;
|
||||||
return new PasswordAccessStatus
|
return new PasswordAccessStatus
|
||||||
{
|
{
|
||||||
Stage = state.Stage,
|
Stage = state.Stage,
|
||||||
CanLaunch = true,
|
CanLaunch = true,
|
||||||
IsPermanent = false,
|
IsPermanent = false,
|
||||||
ShouldPromptAtStartup = state.Stage == 1 && remainingDays <= ExpirationReminderDays,
|
ShouldPromptAtStartup = isReminderWindow,
|
||||||
CanSubmitPassword = state.Stage == 1 && remainingDays <= ExpirationReminderDays,
|
CanSubmitPassword = false,
|
||||||
StageText = state.Stage == 1 ? "当前阶段:第 1 次时效(15 天)" : "当前阶段:第 2 次时效(30 天)",
|
StageText = isInitialStage ? $"当前阶段:首次使用({InitialAccessDays} 天)" : $"当前阶段:第 1 次续期({ExtendedAccessDays} 天)",
|
||||||
StatusTitle = state.Stage == 1 && remainingDays <= ExpirationReminderDays ? "第 1 次时效即将到期" : "时效有效",
|
StatusTitle = isReminderWindow
|
||||||
StatusDetail = state.Stage == 1 && remainingDays <= ExpirationReminderDays
|
? isInitialStage ? "首次使用即将到期" : "第 1 次续期即将到期"
|
||||||
? $"剩余 {remainingDays} 天,可提前输入 30 天密码。"
|
: "时效有效",
|
||||||
|
StatusDetail = isReminderWindow
|
||||||
|
? isInitialStage
|
||||||
|
? $"剩余 {remainingDays} 天,到期后需输入第 1 次时效密码。"
|
||||||
|
: $"剩余 {remainingDays} 天,到期后需输入第 2 次时效密码。"
|
||||||
: $"当前可直接进入系统。",
|
: $"当前可直接进入系统。",
|
||||||
RemainingDays = remainingDays,
|
RemainingDays = remainingDays,
|
||||||
ExpiresAt = state.ExpiresAt
|
ExpiresAt = state.ExpiresAt
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.Stage == 1)
|
if (state.Stage == 0)
|
||||||
{
|
{
|
||||||
return new PasswordAccessStatus
|
return new PasswordAccessStatus
|
||||||
{
|
{
|
||||||
Stage = 1,
|
Stage = 0,
|
||||||
CanLaunch = false,
|
CanLaunch = false,
|
||||||
IsPermanent = false,
|
IsPermanent = false,
|
||||||
ShouldPromptAtStartup = true,
|
ShouldPromptAtStartup = true,
|
||||||
CanSubmitPassword = true,
|
CanSubmitPassword = true,
|
||||||
StageText = "当前阶段:第 1 次时效已到期",
|
StageText = "当前阶段:首次使用已到期",
|
||||||
StatusTitle = "需要输入第 2 次时效密码",
|
StatusTitle = "需要输入第 1 次时效密码",
|
||||||
StatusDetail = $"输入 30 天密码后继续使用。",
|
StatusDetail = $"输入密码后继续使用 {ExtendedAccessDays} 天。",
|
||||||
RemainingDays = 0,
|
RemainingDays = 0,
|
||||||
ExpiresAt = state.ExpiresAt
|
ExpiresAt = state.ExpiresAt
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var permanentState = new PasswordAccessState
|
|
||||||
{
|
|
||||||
Stage = 3,
|
|
||||||
ActivatedAt = state.ActivatedAt,
|
|
||||||
ExpiresAt = null
|
|
||||||
};
|
|
||||||
|
|
||||||
if (persistState)
|
|
||||||
{
|
|
||||||
SaveState(permanentState);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PasswordAccessStatus
|
return new PasswordAccessStatus
|
||||||
{
|
{
|
||||||
Stage = 3,
|
Stage = 1,
|
||||||
CanLaunch = true,
|
CanLaunch = false,
|
||||||
IsPermanent = true,
|
IsPermanent = false,
|
||||||
ShouldPromptAtStartup = false,
|
ShouldPromptAtStartup = true,
|
||||||
CanSubmitPassword = false,
|
CanSubmitPassword = true,
|
||||||
StageText = "当前阶段:永久有效",
|
StageText = "当前阶段:第 1 次续期已到期",
|
||||||
StatusTitle = "系统已永久有效",
|
StatusTitle = "需要输入第 2 次时效密码",
|
||||||
StatusDetail = "当前可直接进入系统。",
|
StatusDetail = "输入密码后系统转为永久有效。",
|
||||||
RemainingDays = int.MaxValue
|
RemainingDays = 0,
|
||||||
|
ExpiresAt = state.ExpiresAt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetStageDays(int stage) => stage switch
|
||||||
|
{
|
||||||
|
0 => InitialAccessDays,
|
||||||
|
1 => ExtendedAccessDays,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
|
||||||
|
private static string GetStageName(int stage) => stage switch
|
||||||
|
{
|
||||||
|
0 => "首次使用阶段",
|
||||||
|
1 => "第 1 次续期阶段",
|
||||||
|
_ => "当前阶段"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static PasswordAccessState LoadOrCreateState()
|
||||||
|
{
|
||||||
|
var state = LoadState();
|
||||||
|
if (state is not null)
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
var initialState = CreateInitialState();
|
||||||
|
SaveState(initialState);
|
||||||
|
return initialState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PasswordAccessState CreateInitialState()
|
||||||
|
{
|
||||||
|
var now = DateTime.Now;
|
||||||
|
return new PasswordAccessState
|
||||||
|
{
|
||||||
|
Stage = 0,
|
||||||
|
ActivatedAt = now,
|
||||||
|
ExpiresAt = now.AddDays(InitialAccessDays)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user