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

Accept terms of Service at signup #8193

Merged
merged 23 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a44f782
Adapt create org route in backend to accept terms of service version
frcroth Nov 13, 2024
b62721f
Merge branch 'master' into accept-tos-at-sign-up
frcroth Nov 13, 2024
94716a7
fix inconsistency
frcroth Nov 13, 2024
5607fcc
Fix formatting
frcroth Nov 13, 2024
05eed1c
start to implement frontend
knollengewaechs Nov 14, 2024
ae61dc6
delete old tos modal, add checkboxes to forms and add style
knollengewaechs Nov 14, 2024
5340755
improve styling and remove random new test file
knollengewaechs Nov 15, 2024
ce2396f
Merge branch 'master' into accept-tos-at-sign-up
knollengewaechs Nov 15, 2024
4ea0446
Supply user access context at sign up tos acceptance
frcroth Nov 18, 2024
77e2a59
send org name as id
knollengewaechs Nov 18, 2024
b1bb0b8
add tos modal again
knollengewaechs Nov 18, 2024
a4817e4
Merge branch 'master' into accept-tos-at-sign-up
knollengewaechs Nov 18, 2024
f52c528
Fix frontend lint
frcroth Nov 18, 2024
2602e5b
Add changelog
frcroth Nov 20, 2024
e5d5f19
Revert "send org name as id"
frcroth Nov 20, 2024
db456d0
Merge branch 'master' into accept-tos-at-sign-up
frcroth Nov 20, 2024
377d289
Require terms of service at sign up if enabled
frcroth Nov 20, 2024
8d618c4
invert logic for rendering tos checkbox
knollengewaechs Nov 21, 2024
6c819e3
Add explanation on tos failure because of non-acceptance
frcroth Nov 25, 2024
1d2ecb2
Revert changes to application.conf
frcroth Nov 25, 2024
94be416
Merge branch 'master' into accept-tos-at-sign-up
frcroth Nov 25, 2024
d60afaa
extract TOS checkbox to component
knollengewaechs Nov 25, 2024
ca427bc
Merge branch 'master' into accept-tos-at-sign-up
frcroth Nov 27, 2024
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
22 changes: 17 additions & 5 deletions app/controllers/AuthenticationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import org.apache.commons.codec.digest.{HmacAlgorithms, HmacUtils}
import play.api.data.Form
import play.api.data.Forms.{email, _}
import play.api.data.validation.Constraints._
import play.api.i18n.Messages
import play.api.i18n.{Messages, MessagesProvider}
import play.api.libs.json._
import play.api.mvc.{Action, AnyContent, Cookie, PlayBodyParsers, Request, Result}
import security.{
Expand Down Expand Up @@ -621,6 +621,8 @@ class AuthenticationController @Inject()(
dataStoreToken <- bearerTokenAuthenticatorService.createAndInitDataStoreTokenForUser(user)
_ <- organizationService
.createOrganizationDirectory(organization._id, dataStoreToken) ?~> "organization.folderCreation.failed"
_ <- Fox.runOptional(signUpData.acceptedTermsOfService)(version =>
acceptTermsOfServiceForUser(user, version))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance error handling for Terms of Service acceptance

The ToS acceptance is handled after user creation, but failures in acceptTermsOfServiceForUser might not be properly propagated. Consider:

  1. Validating the ToS version before acceptance
  2. Handling ToS acceptance failures explicitly
- _ <- Fox.runOptional(signUpData.acceptedTermsOfService)(version =>
-   acceptTermsOfServiceForUser(user, version))
+ _ <- Fox.runOptional(signUpData.acceptedTermsOfService) { version =>
+   for {
+     _ <- organizationService.validateTermsOfServiceVersion(version) ?~> "Invalid Terms of Service version"
+     _ <- acceptTermsOfServiceForUser(user, version) ?~> "Failed to accept Terms of Service"
+   } yield ()
+ }

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@frcroth I would prefer if the sign up request gets rejected in case acceptedTermsOfService is not set to true or empty but the application conf says that TOS is enabled.

What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented now.

} yield {
Mailer ! Send(defaultMails
.newOrganizationMail(organization.name, email, request.headers.get("Host").getOrElse("")))
Expand All @@ -637,6 +639,13 @@ class AuthenticationController @Inject()(
)
}

private def acceptTermsOfServiceForUser(user: User, termsOfServiceVersion: Int)(implicit m: MessagesProvider) =
for {
_ <- organizationService.acceptTermsOfService(user._organization, termsOfServiceVersion)(
DBAccessContext(Some(user)),
m)
} yield ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say this can be simplified as organizationService.acceptTermsOfService already returns a Fox[Unit]

Suggested change
for {
_ <- organizationService.acceptTermsOfService(user._organization, termsOfServiceVersion)(
DBAccessContext(Some(user)),
m)
} yield ()
organizationService.acceptTermsOfService(user._organization, termsOfServiceVersion)(DBAccessContext(Some(user)), m)


case class CreateUserInOrganizationParameters(firstName: String,
lastName: String,
email: String,
Expand Down Expand Up @@ -730,7 +739,8 @@ trait AuthForms {
firstName: String,
lastName: String,
password: String,
inviteToken: Option[String])
inviteToken: Option[String],
acceptedTermsOfService: Option[Int])

def signUpForm(implicit messages: Messages): Form[SignUpData] =
Form(
Expand All @@ -745,8 +755,9 @@ trait AuthForms {
"firstName" -> nonEmptyText,
"lastName" -> nonEmptyText,
"inviteToken" -> optional(nonEmptyText),
)((organization, organizationName, email, password, firstName, lastName, inviteToken) =>
SignUpData(organization, organizationName, email, firstName, lastName, password._1, inviteToken))(
"acceptedTermsOfService" -> optional(number)
)((organization, organizationName, email, password, firstName, lastName, inviteToken, acceptTos) =>
SignUpData(organization, organizationName, email, firstName, lastName, password._1, inviteToken, acceptTos))(
signUpData =>
Some(
(signUpData.organization,
Expand All @@ -755,7 +766,8 @@ trait AuthForms {
("", ""),
signUpData.firstName,
signUpData.lastName,
signUpData.inviteToken))))
signUpData.inviteToken,
signUpData.acceptedTermsOfService))))

// Sign in
case class SignInData(email: String, password: String)
Expand Down
6 changes: 1 addition & 5 deletions app/controllers/OrganizationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package controllers
import org.apache.pekko.actor.ActorSystem
import play.silhouette.api.Silhouette
import com.scalableminds.util.accesscontext.{DBAccessContext, GlobalAccessContext}
import com.scalableminds.util.time.Instant
import com.scalableminds.util.tools.{Fox, FoxImplicits}
import mail.{DefaultMails, Send}

Expand Down Expand Up @@ -141,10 +140,7 @@ class OrganizationController @Inject()(
def acceptTermsOfService(version: Int): Action[AnyContent] = sil.SecuredAction.async { implicit request =>
for {
_ <- bool2Fox(request.identity.isOrganizationOwner) ?~> "termsOfService.onlyOrganizationOwner"
_ <- bool2Fox(conf.WebKnossos.TermsOfService.enabled) ?~> "termsOfService.notEnabled"
requiredVersion = conf.WebKnossos.TermsOfService.version
_ <- bool2Fox(version == requiredVersion) ?~> Messages("termsOfService.versionMismatch", requiredVersion, version)
_ <- organizationDAO.acceptTermsOfService(request.identity._organization, version, Instant.now)
_ <- organizationService.acceptTermsOfService(request.identity._organization, version)
} yield Ok
}

Expand Down
14 changes: 12 additions & 2 deletions app/models/organization/OrganizationService.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package models.organization

import com.scalableminds.util.accesscontext.{DBAccessContext, GlobalAccessContext}
import com.scalableminds.util.time.Instant
import com.scalableminds.util.tools.{Fox, FoxImplicits, TextUtils}
import com.scalableminds.webknossos.datastore.rpc.RPC
import com.typesafe.scalalogging.LazyLogging
Expand All @@ -10,6 +11,7 @@ import models.dataset.{DataStore, DataStoreDAO}
import models.folder.{Folder, FolderDAO, FolderService}
import models.team.{PricingPlan, Team, TeamDAO}
import models.user.{Invite, MultiUserDAO, User, UserDAO, UserService}
import play.api.i18n.{Messages, MessagesProvider}
import play.api.libs.json.{JsArray, JsObject, Json}
import utils.{ObjectId, WkConf}

Expand All @@ -24,8 +26,7 @@ class OrganizationService @Inject()(organizationDAO: OrganizationDAO,
folderService: FolderService,
userService: UserService,
rpc: RPC,
conf: WkConf,
)(implicit ec: ExecutionContext)
conf: WkConf)(implicit ec: ExecutionContext)
extends FoxImplicits
with LazyLogging {

Expand Down Expand Up @@ -165,4 +166,13 @@ class OrganizationService @Inject()(organizationDAO: OrganizationDAO,
def newUserMailRecipient(organization: Organization)(implicit ctx: DBAccessContext): Fox[String] =
fallbackOnOwnerEmail(organization.newUserMailingList, organization)

def acceptTermsOfService(organizationId: String, version: Int)(implicit ctx: DBAccessContext,
m: MessagesProvider): Fox[Unit] =
for {
_ <- bool2Fox(conf.WebKnossos.TermsOfService.enabled) ?~> "termsOfService.notEnabled"
requiredVersion = conf.WebKnossos.TermsOfService.version
_ <- bool2Fox(version == requiredVersion) ?~> Messages("termsOfService.versionMismatch", requiredVersion, version)
_ <- organizationDAO.acceptTermsOfService(organizationId, version, Instant.now)
} yield ()

}
4 changes: 2 additions & 2 deletions conf/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ webKnossos {
Please add the information of the operator to comply with GDPR.
"""
termsOfService {
enabled = false
enabled = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undo me

knollengewaechs marked this conversation as resolved.
Show resolved Hide resolved
# The URL will be embedded into an iFrame
url = "https://webknossos.org/terms-of-service"
acceptanceDeadline = "2023-01-01T00:00:00Z"
Expand Down Expand Up @@ -146,7 +146,7 @@ features {
discussionBoard = "https://forum.image.sc/tag/webknossos"
discussionBoardRequiresAdmin = false
hideNavbarLogin = false
isWkorgInstance = false
isWkorgInstance = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undo me too

recommendWkorgInstance = true
taskReopenAllowedInSeconds = 30
allowDeleteDatasets = true
Expand Down
77 changes: 55 additions & 22 deletions frontend/javascripts/admin/auth/registration_form_generic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import Store from "oxalis/throttled_store";
import messages from "messages";
import { setHasOrganizationsAction } from "oxalis/model/actions/ui_actions";
import { setActiveOrganizationAction } from "oxalis/model/actions/organization_actions";
import { useFetch } from "libs/react_helpers";
import { getTermsOfService } from "admin/api/terms_of_service";

const FormItem = Form.Item;
const { Password } = Input;
Expand All @@ -26,6 +28,8 @@ type Props = {
function RegistrationFormGeneric(props: Props) {
const [form] = Form.useForm();

const terms = useFetch(getTermsOfService, null, []);

const onFinish = async (formValues: Record<string, any>) => {
await Request.sendJSONReceiveJSON(
props.organizationIdToCreate != null
Expand Down Expand Up @@ -274,28 +278,57 @@ function RegistrationFormGeneric(props: Props) {
</FormItem>
</Col>
</Row>
{props.hidePrivacyStatement ? null : (
<FormItem
name="privacy_check"
valuePropName="checked"
rules={[
{
validator: (_, value) =>
value
? Promise.resolve()
: Promise.reject(new Error(messages["auth.privacy_check_required"])),
},
]}
>
<Checkbox>
I agree to storage and processing of my personal data as described in the{" "}
<a target="_blank" href="/privacy" rel="noopener noreferrer">
privacy statement
</a>
.
</Checkbox>
</FormItem>
)}
<div className="registration-form-checkboxes">
{props.hidePrivacyStatement ? null : (
<FormItem
name="privacy_check"
valuePropName="checked"
rules={[
{
validator: (_, value) =>
value
? Promise.resolve()
: Promise.reject(new Error(messages["auth.privacy_check_required"])),
},
]}
>
<Checkbox>
I agree to storage and processing of my personal data as described in the{" "}
<a target="_blank" href="/privacy" rel="noopener noreferrer">
privacy statement
</a>
.
</Checkbox>
</FormItem>
)}
{terms != null && !terms.enabled ? null : (
knollengewaechs marked this conversation as resolved.
Show resolved Hide resolved
<FormItem
name="tos_check"
valuePropName="checked"
rules={[
{
validator: (_, value) =>
value
? Promise.resolve()
: Promise.reject(new Error(messages["auth.tos_check_required"])),
},
]}
>
<Checkbox disabled={terms == null}>
I agree to the{" "}
{terms == null ? (
"terms of service"
) : (
<a target="_blank" href={terms.url} rel="noopener noreferrer">
terms of service
</a>
)}
.
</Checkbox>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add loading state for terms of service checkbox

The checkbox is disabled when terms are loading, but there's no visual indication to the user.

Consider adding a loading state:

-<Checkbox disabled={terms == null}>
+<Checkbox disabled={terms == null}>
+  {terms == null ? (
+    <span>
+      <LoadingOutlined spin /> Loading terms of service...
+    </span>
+  ) : (
     I agree to the{" "}
     <a target="_blank" href={terms.url} rel="noopener noreferrer">
       terms of service
     </a>
     .
+  )}
 </Checkbox>

Committable suggestion skipped: line range outside the PR's diff.

</FormItem>
)}
</div>

<FormItem>
<Button
size="large"
Expand Down
107 changes: 67 additions & 40 deletions frontend/javascripts/admin/auth/registration_form_wkorg.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Form, Input, Button, Row, Col, Checkbox } from "antd";
import { UserOutlined, LockOutlined, MailOutlined } from "@ant-design/icons";
import { useRef, memo } from "react";
import { memo } from "react";
import { loginUser } from "admin/admin_rest_api";
import { setActiveUserAction } from "oxalis/model/actions/user_actions";
import Request from "libs/request";
import Store from "oxalis/throttled_store";
import messages from "messages";
import { setActiveOrganizationAction } from "oxalis/model/actions/organization_actions";
import { useFetch } from "libs/react_helpers";
import { getTermsOfService } from "admin/api/terms_of_service";

const FormItem = Form.Item;
const { Password } = Input;
Expand All @@ -15,34 +17,34 @@ type Props = {
onRegistered: (isUserLoggedIn: true) => void;
};

function generateOrganizationId() {
let output = "";

for (let i = 0; i < 8; i++) {
output += Math.floor(Math.random() * 255)
.toString(16)
.padStart(2, "0");
}
function generateOrganizationId(firstName: string, lastName: string) {
return `${firstName.toLowerCase()}-${lastName.toLowerCase()}-lab`;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input sanitization to prevent invalid organization IDs.

The organization ID generation could produce invalid or duplicate IDs. Consider:

  • Sanitizing special characters and spaces
  • Adding uniqueness suffix
  • Handling edge cases (empty strings, very long names)
 function generateOrganizationId(firstName: string, lastName: string) {
-  return `${firstName.toLowerCase()}-${lastName.toLowerCase()}-lab`;
+  const sanitize = (str: string) => str
+    .toLowerCase()
+    .trim()
+    .replace(/[^a-z0-9-]/g, '')
+    .replace(/-+/g, '-');
+  const timestamp = Date.now().toString(36);
+  return `${sanitize(firstName)}-${sanitize(lastName)}-lab-${timestamp}`;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function generateOrganizationId(firstName: string, lastName: string) {
return `${firstName.toLowerCase()}-${lastName.toLowerCase()}-lab`;
}
function generateOrganizationId(firstName: string, lastName: string) {
const sanitize = (str: string) => str
.toLowerCase()
.trim()
.replace(/[^a-z0-9-]/g, '')
.replace(/-+/g, '-');
const timestamp = Date.now().toString(36);
return `${sanitize(firstName)}-${sanitize(lastName)}-lab-${timestamp}`;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might create naming collisions. I'd like to double check this with @fm3

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this way of defining the orga id might lead to orga ids with whitespaces in it 🤔

Copy link
Member

@fm3 fm3 Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change this in this PR at all? As I understand, the random-character string is supposed to be the typical organization id. The organization name on the other hand is supposed to be created from the user name.

This was introduced in #4439 (though organizationId was still called organizationName then, and what is now the name was then the displayName).

I agree that changing it to firstname-lastname-lab may lead to unwanted collisions.

It’s true that some old organizations have ids like scalable_minds or sample_organization but it is indeed intended that new ones created by this form should have the random string. #7386 did not change that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it is also kinda strange, why the frontend generates this id string and not the backend 🤔. Maybe this could be changed in the future?

but it is indeed intended that new ones created by this form should have the random string.

@dieknolle3333 Could you please undo this change here? In case we agree to change the id generation, I'd do this in a separate PR. But I'd say that this is kinda unlikely because an id being a random hex string sounds fine to me. But feel free to open up a discussion on this :) (@frcroth)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is undone. I interpreted the PR and the issue so that the id should be human readable now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that indeed looks like a misunderstanding 🙈

Thanks a lot for undoing the change so fast :) 🙏

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it is also kinda strange, why the frontend generates this id string and not the backend 🤔. Maybe this could be changed in the future?

Wrote #8216 to track that and future discussion of what the IDs should look like.

I interpreted the PR and the issue so that the id should be human readable now.

Fair, but it was more of the opposite, really. Before #7386 there was a mongoId and this random string as organizationName, and the actual name (then called displayName), with spaces and all. In the PR, we dropped the mongoId and declared this random string the id, because it already had to be unique and was used as a key in many places.

Thanks to you all for clearing this up here :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for removing this, felix, and clearing this up everyone!


return output;
function generateOrganizationName(firstName: string, lastName: string) {
return `${firstName} ${lastName} Lab`;
}

function RegistrationFormWKOrg(props: Props) {
const [form] = Form.useForm();
const organizationId = useRef(generateOrganizationId());
const terms = useFetch(getTermsOfService, null, []);

async function onFinish(formValues: Record<string, any>) {
const { firstName, lastName } = formValues;
const trimmedFirstName = firstName.trim();
const trimmedLastName = lastName.trim();
await Request.sendJSONReceiveJSON("/api/auth/createOrganizationWithAdmin", {
data: {
...formValues,
firstName: formValues.firstName.trim(),
lastName: formValues.lastName.trim(),
firstName: trimmedFirstName,
lastName: trimmedLastName,
password: {
password1: formValues.password.password1,
password2: formValues.password.password1,
},
organization: organizationId.current,
organizationName: `${formValues.firstName.trim()} ${formValues.lastName.trim()} Lab`,
organization: generateOrganizationId(trimmedFirstName, trimmedLastName),
organizationName: generateOrganizationName(trimmedFirstName, trimmedLastName),
acceptedTermsOfService: terms?.version,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

🛠️ Refactor suggestion

Based on the findings, I can now generate the final response.

Add error handling for organization creation and display feedback to the user

The form submission should handle API errors and provide user feedback using the antd message component, which is the standard error display mechanism in the codebase.

  • Add try-catch block around the API call
  • Display error feedback using message.error
  • Show success message using message.success
 async function onFinish(formValues: Record<string, any>) {
+  try {
     const { firstName, lastName } = formValues;
     const trimmedFirstName = firstName.trim();
     const trimmedLastName = lastName.trim();
     await Request.sendJSONReceiveJSON("/api/auth/createOrganizationWithAdmin", {
       data: {
         ...formValues,
         firstName: trimmedFirstName,
         lastName: trimmedLastName,
         password: {
           password1: formValues.password.password1,
           password2: formValues.password.password1,
         },
         organization: generateOrganizationId(trimmedFirstName, trimmedLastName),
         organizationName: generateOrganizationName(trimmedFirstName, trimmedLastName),
         acceptedTermsOfService: terms?.version,
       },
     });
+    message.success("Organization created successfully");
+  } catch (error) {
+    message.error("Failed to create organization. Please try again.");
+    console.error("Organization creation failed:", error);
+    return;
+  }
🔗 Analysis chain

Add error handling for organization creation.

The form submission lacks proper error handling for the API call. Also, verify the impact of failed organization creation on the subsequent login attempt.

 async function onFinish(formValues: Record<string, any>) {
+  try {
     const { firstName, lastName } = formValues;
     const trimmedFirstName = firstName.trim();
     const trimmedLastName = lastName.trim();
     await Request.sendJSONReceiveJSON("/api/auth/createOrganizationWithAdmin", {
       data: {
         ...formValues,
         firstName: trimmedFirstName,
         lastName: trimmedLastName,
         password: {
           password1: formValues.password.password1,
           password2: formValues.password.password1,
         },
         organization: generateOrganizationId(trimmedFirstName, trimmedLastName),
         organizationName: generateOrganizationName(trimmedFirstName, trimmedLastName),
         acceptedTermsOfService: terms?.version,
       },
     });
+  } catch (error) {
+    console.error('Failed to create organization:', error);
+    // Consider showing error message to user
+    return;
+  }

Let me gather more context about the error handling patterns in the codebase.


Let me check how error handling is implemented in other form submissions and authentication flows.


Let me check for the Request utility implementation and any error handling patterns it might have.


Let me check how the Request utility handles errors and if there's any global error handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for error handling patterns in similar form submission implementations
rg -A 5 "sendJSONReceiveJSON.*createOrganizationWithAdmin"

Length of output: 630


Script:

#!/bin/bash
# Check for error handling patterns in similar form submissions using Request.sendJSONReceiveJSON
rg -B 2 -A 5 "try.*Request\.sendJSONReceiveJSON"

# Look for any notification or error display components used in the codebase
ast-grep --pattern 'import { $_ } from "antd"'

Length of output: 3664


Script:

#!/bin/bash
# Look for similar form submissions in auth-related components
rg -B 3 -A 10 "async.*onFinish.*formValues" frontend/javascripts/admin/auth/

# Check for any existing error message handling in auth components
rg -B 2 -A 5 "message\.(error|warning)" frontend/javascripts/admin/auth/

Length of output: 1545


Script:

#!/bin/bash
# Look for Request utility implementation
rg -B 2 -A 10 "class.*Request" 

# Check for any error handling in the Request class
rg -B 2 -A 10 "sendJSONReceiveJSON.*=.*async" 

# Look for any error handling patterns in the auth flow
ast-grep --pattern 'catch (error) { $$$_ }'

Length of output: 36038


Script:

#!/bin/bash
# Look for error handling in the Request class implementation
rg -B 5 -A 10 "triggerRequest" frontend/javascripts/libs/request.ts

# Check for any global error handlers or message displays
rg -B 2 -A 5 "message\.(error|success)" frontend/javascripts/

Length of output: 10511

});
const [user, organization] = await loginUser({
Expand Down Expand Up @@ -155,32 +157,57 @@ function RegistrationFormWKOrg(props: Props) {
placeholder="Password"
/>
</FormItem>
<div className="registration-form-checkboxes">
<FormItem
name="privacy_check"
valuePropName="checked"
rules={[
{
validator: (_, value) =>
value
? Promise.resolve()
: Promise.reject(new Error(messages["auth.privacy_check_required"])),
},
]}
>
<Checkbox>
I agree to storage and processing of my personal data as described in the{" "}
<a target="_blank" href="/privacy" rel="noopener noreferrer">
privacy statement
</a>
.
</Checkbox>
</FormItem>

<FormItem
name="privacy_check"
valuePropName="checked"
rules={[
{
validator: (_, value) =>
value
? Promise.resolve()
: Promise.reject(new Error(messages["auth.privacy_check_required"])),
},
]}
>
<Checkbox>
I agree to storage and processing of my personal data as described in the{" "}
<a target="_blank" href="/privacy" rel="noopener noreferrer">
privacy statement
</a>
.
</Checkbox>
</FormItem>
<FormItem
style={{
marginBottom: 10,
}}
>
{terms != null && !terms.enabled ? null : (
knollengewaechs marked this conversation as resolved.
Show resolved Hide resolved
<FormItem
name="tos_check"
valuePropName="checked"
rules={[
{
validator: (_, value) =>
value
? Promise.resolve()
: Promise.reject(new Error(messages["auth.tos_check_required"])),
},
]}
>
<Checkbox disabled={terms == null}>
I agree to the{" "}
{terms == null ? (
"terms of service"
) : (
<a target="_blank" href={terms.url} rel="noopener noreferrer">
terms of service
</a>
)}
.
</Checkbox>
</FormItem>
)}
</div>

<FormItem>
<Button
size="large"
type="primary"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ class ExplorativeAnnotationsView extends React.PureComponent<Props, State> {
</div>
<div className="flex-container">
<div className="flex-item" style={{ flexGrow: 0 }}>
{teamTags.length > 0 ? <TeamOutlined className="icon-margin-right"/> : null}
{teamTags.length > 0 ? <TeamOutlined className="icon-margin-right" /> : null}
</div>
<div className="flex-item">{teamTags}</div>
</div>
Expand Down
Loading