Skip to content

Commit

Permalink
accept invite to new tenant for the existing user
Browse files Browse the repository at this point in the history
  • Loading branch information
larinam committed Aug 24, 2024
1 parent 910af18 commit e9241b7
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 28 deletions.
39 changes: 28 additions & 11 deletions backend/routers/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,13 @@ async def get_invite_details(token: str):
if not tenant:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Associated tenant not found")

existing_user = User.objects(email=invite.email).first() is not None

return {
"email": invite.email,
"tenant_name": tenant.name,
"tenant_identifier": tenant.identifier
"tenant_identifier": tenant.identifier,
"existing_user": existing_user
}


Expand All @@ -314,20 +317,34 @@ async def register_user_via_invite(token: str, user_creation: UserCreationModel)
if not invite or invite.is_expired():
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid or expired invitation token")

# Create the user and associate with the tenant
user = User()
user.tenants = [invite.tenant]
user.name = user_creation.name
user.email = invite.email
user.auth_details = AuthDetails(username=user_creation.username,
telegram_username=user_creation.telegram_username if user_creation.telegram_username else None)
user.hash_password(user_creation.password)
user.save()
# Check if the user already exists based on the email from the invite
user = User.objects(email=invite.email).first()

if user:
# User exists, add the new tenant
if invite.tenant in user.tenants:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="User already associated with this tenant")

user.tenants.append(invite.tenant)
user.save()
else:
# User doesn't exist, create a new one
user = User()
user.tenants = [invite.tenant]
user.name = user_creation.name
user.email = invite.email
user.auth_details = AuthDetails(
username=user_creation.username,
telegram_username=user_creation.telegram_username if user_creation.telegram_username else None
)
user.hash_password(user_creation.password)
user.save()

# Mark invite as accepted
invite.mark_as_accepted()

return {"message": "User registered successfully"}
return {"message": "User registered successfully" if not user else "Tenant associated successfully with the existing user"}



class UserInviteDTO(BaseModel):
Expand Down
56 changes: 39 additions & 17 deletions frontend/src/components/auth/UserRegistration.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import './InitialUserCreation.css';

const UserRegistration = () => {
const navigate = useNavigate();
const { token } = useParams(); // Get the token from the URL
const { apiCall } = useApi();
const {token} = useParams(); // Get the token from the URL
const {apiCall} = useApi();
const [tenantName, setTenantName] = useState('');
const [tenantIdentifier, setTenantIdentifier] = useState('');
const [email, setEmail] = useState('');
const [name, setName] = useState('');
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [existingUser, setExistingUser] = useState(false);

useEffect(() => {
const fetchInviteDetails = async () => {
Expand All @@ -22,6 +23,7 @@ const UserRegistration = () => {
setTenantName(data.tenant_name);
setTenantIdentifier(data.tenant_identifier);
setEmail(data.email);
setExistingUser(data.existing_user);
} catch (error) {
console.error('Error fetching invite details:', error);
toast.error("Invalid or expired invitation link.");
Expand All @@ -34,36 +36,56 @@ const UserRegistration = () => {
const handleSubmit = async (e) => {
e.preventDefault();
try {
await apiCall(`/users/register/${token}`, 'POST', { name, email, username, password });
const data = await apiCall(`/users/register/${token}`, 'POST', {
name,
email,
username,
password
});
toast.success(data.message);
navigate('/login');
} catch (error) {
console.error('Error registering user:', error);
toast.error("An error occurred. Please try again.");
}
};


return (
<div className="initialUserCreationContainer">
<h1>Register Your Account</h1>
<h1>{existingUser ? 'User Already Exists' : 'Register Your Account'}</h1>
<button
className="logInButton"
onClick={() => navigate('/login')}
>
Log in
</button>
<form onSubmit={handleSubmit} className="formStyle">
<input type="text" className="inputStyle" value={tenantName} disabled placeholder="Workspace Name" required />
<input type="text" className="inputStyle" value={tenantIdentifier} disabled placeholder="Workspace Code" required />
<hr width={"100%"} />
<input type="text" autoComplete={"name"} className="inputStyle" value={name}
onChange={(e) => setName(e.target.value)} placeholder="Name" required autoFocus />
<input type="email" name="email" className="inputStyle" value={email} disabled placeholder="Email" required />
<input type="text" name="username" autoComplete={"username"} className="inputStyle" value={username}
onChange={(e) => setUsername(e.target.value)} placeholder="Username" required />
<input type="password" name="new-password" autoComplete={"new-password"} className="inputStyle" value={password}
onChange={(e) => setPassword(e.target.value)} placeholder="Password" required />
<button type="submit" className="buttonStyle createWorkspaceButton">Register</button>
</form>
{existingUser ? (
<div className="existingUserMessage">
<p>A user with email {email} already exists in the system.</p>
<p>You can accept the invitation to join the workspace with the name "{tenantName}" and identifier
"{tenantIdentifier}".</p>
<form onSubmit={handleSubmit} className="formStyle">
<button type="submit" className="buttonStyle createWorkspaceButton">Accept invite</button>
</form>
</div>
) : (
<form onSubmit={handleSubmit} className="formStyle">
<input type="text" className="inputStyle" value={tenantName} disabled placeholder="Workspace Name" required/>
<input type="text" className="inputStyle" value={tenantIdentifier} disabled placeholder="Workspace Code"
required/>
<hr width={"100%"}/>
<input type="text" autoComplete={"name"} className="inputStyle" value={name}
onChange={(e) => setName(e.target.value)} placeholder="Name" required autoFocus/>
<input type="email" name="email" className="inputStyle" value={email} disabled placeholder="Email" required/>
<input type="text" name="username" autoComplete={"username"} className="inputStyle" value={username}
onChange={(e) => setUsername(e.target.value)} placeholder="Username" required/>
<input type="password" name="new-password" autoComplete={"new-password"} className="inputStyle"
value={password}
onChange={(e) => setPassword(e.target.value)} placeholder="Password" required/>
<button type="submit" className="buttonStyle createWorkspaceButton">Register</button>
</form>
)}
</div>
);
};
Expand Down

0 comments on commit e9241b7

Please sign in to comment.