Skip to content

Commit

Permalink
Validated email on frontend and various other small upgrades
Browse files Browse the repository at this point in the history
  • Loading branch information
tjcouch-sil committed Nov 4, 2024
1 parent d2bec2c commit 2b8437a
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 35 deletions.
9 changes: 7 additions & 2 deletions c-sharp/JsonUtils/RegistrationDataConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,19 @@ JsonSerializerOptions options
string supporterName = "";

string? lastPropertyName = null;
while (reader.Read())
// The starting token is consumed before we get the reader
int onObjectLevel = 1;
while (onObjectLevel > 0 && reader.Read())
{
switch (reader.TokenType)
{
case JsonTokenType.StartObject:
case JsonTokenType.EndObject:
case JsonTokenType.StartArray:
onObjectLevel++;
break;
case JsonTokenType.EndObject:
case JsonTokenType.EndArray:
onObjectLevel--;
break;
case JsonTokenType.PropertyName:
lastPropertyName = reader.GetString();
Expand Down
46 changes: 16 additions & 30 deletions c-sharp/Users/ParatextRegistrationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ await PapiClient.RegisterRequestHandlerAsync(

#endregion

#region Protected properties and methods
#region Private properties and methods

protected PapiClient PapiClient { get; } = papiClient;
private PapiClient PapiClient { get; } = papiClient;

/// <summary>
/// Returns information about user's current Paratext Registry user information in ParatextData.dll
/// </summary>
/// <param name="requestContents">Contents of command request. No contents expected</param>
/// <returns>Paratext registration information</returns>
protected RegistrationData GetParatextRegistrationData()
private RegistrationData GetParatextRegistrationData()
{
try
{
Expand Down Expand Up @@ -86,7 +86,7 @@ protected RegistrationData GetParatextRegistrationData()
/// </summary>
/// <param name="requestContents">Contents of command request. Array whose first entry is the registration data object</param>
/// <returns>`true` if successfully updated; `false` otherwise</returns>
protected void SetParatextRegistrationData(RegistrationData newRegistrationData)
private void SetParatextRegistrationData(RegistrationData newRegistrationData)
{
bool shouldSkipAppendingToExceptionMessage = false;
try
Expand Down Expand Up @@ -154,6 +154,7 @@ protected void SetParatextRegistrationData(RegistrationData newRegistrationData)
!string.IsNullOrEmpty(RegistrationInfo.DefaultUser.Name)
&& RegistrationInfo.DefaultUser.Name != newRegistrationData.Name
)
{
try
{
PrepareForUserChange();
Expand All @@ -164,35 +165,24 @@ protected void SetParatextRegistrationData(RegistrationData newRegistrationData)
$"Exception while committing existing changes to prepare to change users: {e}"
);
}
}

// Actually change the registration info
RegistrationInfo.ChangeRegistrationData(newRegistrationData);

// registration code may have changed, so reset the registry server with the new user data
RegistryServer.Default?.ResetServer(RegistrationInfo.DefaultUser);

// No need to observe this task in any way. We are scheduling a call to restart the application then
// returning from this method to continue execution and properly return from this method.
#pragma warning disable VSTHRD110 // Observe result of async calls
// Restart the application after a delay. Don't wait for it so the response goes through
Task.Delay(REGISTRATION_CHANGE_RESTART_DELAY_MS)
.ContinueWith(
async (Task task) =>
{
try
{
await PapiClient.SendRequestAsync("command:platform.restart", []);
}
catch (Exception e)
{
Console.WriteLine(
$"Error while requesting to restart the application: {e}"
);
}
},
TaskScheduler.Default
);
#pragma warning restore VSTHRD110 // Observe result of async calls
ThreadingUtils.RunTask(
Task.Delay(REGISTRATION_CHANGE_RESTART_DELAY_MS)
.ContinueWith(
async (Task task) =>
await PapiClient.SendRequestAsync("command:platform.restart", []),
TaskScheduler.Default
),
"ParatextRegistrationService sending request to restart the application"
);
}
catch (Exception e)
{
Expand All @@ -205,15 +195,11 @@ protected void SetParatextRegistrationData(RegistrationData newRegistrationData)
}
}

#endregion

#region Private properties and methods

/// <summary>
/// For any project with uncommitted changes on this machine, marks a point in project history in
/// preparation for switching to a different Paratext user.
///
/// Adapted from `UserSwitchingHelper.PrepareForUserChange
/// Adapted from `UserSwitchingHelper.PrepareForUserChange`
/// </summary>
private void PrepareForUserChange()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ enum SaveState {

const REGISTRATION_CODE_LENGTH_WITH_DASHES = 34;
const REGISTRATION_CODE_REGEX_STRING =
'^(?:[a-zA-Z0-9]{6}-[a-zA-Z0-9]{6}-[a-zA-Z0-9]{6}-[a-zA-Z0-9]{6}-[a-zA-Z0-9]{6}|\\*\\*\\*\\*\\*\\*-\\*\\*\\*\\*\\*\\*-\\*\\*\\*\\*\\*\\*-\\*\\*\\*\\*\\*\\*-\\*\\*\\*\\*\\*\\*)$';
'^(?:[a-zA-Z0-9]{6}-[a-zA-Z0-9]{6}-[a-zA-Z0-9]{6}-[a-zA-Z0-9]{6}-[a-zA-Z0-9]{6}|\\*{6}-\\*{6}-\\*{6}-\\*{6}-\\*{6})$';
const EMAIL_REGEX_STRING = '^.+@.+\\..+$';

/** Just a div with some margins to give some space around parts of the web view */
function Section({ children, className }: GenericComponentProps) {
Expand Down Expand Up @@ -138,8 +139,9 @@ globalThis.webViewComponent = function ParatextRegistration({ useWebViewState }:
currentRegistrationData.code !== registrationCode ||
currentRegistrationData.email !== email ||
currentRegistrationData.supporterName !== supporter;
// whether the code seems valid according to a quick check
// whether the code and email seem valid according to a quick check
const isCodeValid = !!registrationCode.match(REGISTRATION_CODE_REGEX_STRING);
const isEmailValid = !!email.match(EMAIL_REGEX_STRING);

return (
<div className="tw-p-2 tw-flex tw-flex-col tw-justify-between tw-h-screen">
Expand All @@ -163,6 +165,8 @@ globalThis.webViewComponent = function ParatextRegistration({ useWebViewState }:
/>
<span>{localizedStrings['%paratextRegistration_label_emailAddress%']}</span>
<Input
className="invalid:tw-border-destructive"
pattern={EMAIL_REGEX_STRING}
value={email}
disabled={isFormDisabled}
onChange={(e) => setEmail(e.target.value)}
Expand Down Expand Up @@ -205,7 +209,7 @@ globalThis.webViewComponent = function ParatextRegistration({ useWebViewState }:
<span />
<Button
variant="destructive"
disabled={isFormDisabled || !hasUnsavedChanges || !isCodeValid}
disabled={isFormDisabled || !hasUnsavedChanges || !isCodeValid || !isEmailValid}
onClick={saveAndRestart}
>
{saveState === SaveState.IsSaving ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ declare module 'papi-shared-types' {
/**
* Gets information about user's current Paratext Registry user information in
* `ParatextData.dll`
*
* Note that this does not return the user's registration code as it is secure information.
* Instead, it returns `******-******-******-******-******` in its place.
*/
'paratextRegistration.getParatextRegistrationData': () => Promise<RegistrationData>;
/**
Expand Down

0 comments on commit 2b8437a

Please sign in to comment.