@@ -3,7 +3,7 @@ import { useTranslate } from "@probo/i18n";
|
|||||||
import { Button, Field, IconChevronLeft, useToast } from "@probo/ui";
|
import { Button, Field, IconChevronLeft, useToast } from "@probo/ui";
|
||||||
import type { FormEventHandler } from "react";
|
import type { FormEventHandler } from "react";
|
||||||
import { useMutation } from "react-relay";
|
import { useMutation } from "react-relay";
|
||||||
import { Link, useLocation, useSearchParams } from "react-router";
|
import { Link, useLocation, useNavigate, useSearchParams } from "react-router";
|
||||||
import { graphql } from "relay-runtime";
|
import { graphql } from "relay-runtime";
|
||||||
|
|
||||||
import type { PasswordSignInPageMutation } from "#/__generated__/iam/PasswordSignInPageMutation.graphql";
|
import type { PasswordSignInPageMutation } from "#/__generated__/iam/PasswordSignInPageMutation.graphql";
|
||||||
@@ -21,6 +21,7 @@ const signInMutation = graphql`
|
|||||||
export default function PasswordSignInPage() {
|
export default function PasswordSignInPage() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
@@ -58,7 +59,7 @@ export default function PasswordSignInPage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.location.href = searchParams.get("redirect-path") ?? "/";
|
void navigate(searchParams.get("redirect-path") ?? "/");
|
||||||
},
|
},
|
||||||
onError: (e) => {
|
onError: (e) => {
|
||||||
toast({
|
toast({
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default function SSOSignInPage() {
|
|||||||
<>
|
<>
|
||||||
<form className="space-y-6 w-full max-w-md mx-auto pt-4" onSubmit={handleSSOCheck}>
|
<form className="space-y-6 w-full max-w-md mx-auto pt-4" onSubmit={handleSSOCheck}>
|
||||||
<Link
|
<Link
|
||||||
to={{ pathname: "/auth/register", search: location.search }}
|
to={{ pathname: "/auth/login", search: location.search }}
|
||||||
className="flex items-center gap-2 text-txt-secondary hover:text-txt-primary transition-colors mb-4"
|
className="flex items-center gap-2 text-txt-secondary hover:text-txt-primary transition-colors mb-4"
|
||||||
>
|
>
|
||||||
<IconChevronLeft size={20} />
|
<IconChevronLeft size={20} />
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ export function MembershipCard(props: MembershipCardProps) {
|
|||||||
fragment,
|
fragment,
|
||||||
fKey,
|
fKey,
|
||||||
);
|
);
|
||||||
const isAssuming = !!lastSession;
|
|
||||||
const isExpired
|
const isExpired
|
||||||
= lastSession && parseDate(lastSession.expiresAt) < new Date();
|
= lastSession && parseDate(lastSession.expiresAt) < new Date();
|
||||||
|
const isAssuming = !!lastSession && !isExpired;
|
||||||
|
|
||||||
const getAuthBadge = () => {
|
const getAuthBadge = () => {
|
||||||
if (isAssuming) {
|
if (isAssuming) {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ function AssumePageInner() {
|
|||||||
search.set("organization-id", organizationId);
|
search.set("organization-id", organizationId);
|
||||||
search.set("redirect-path", redirectPath);
|
search.set("redirect-path", redirectPath);
|
||||||
|
|
||||||
void navigate({ pathname: "/auth/passord-login", search: "?" + search.toString() });
|
void navigate({ pathname: "/auth/password-login", search: "?" + search.toString() });
|
||||||
break;
|
break;
|
||||||
case "SAMLAuthenticationRequired":
|
case "SAMLAuthenticationRequired":
|
||||||
samlSSOLoginURL = new URL(result.redirectUrl);
|
samlSSOLoginURL = new URL(result.redirectUrl);
|
||||||
|
|||||||
@@ -321,11 +321,12 @@ func (s SessionService) OpenPasswordChildSessionForOrganization(
|
|||||||
organizationID gid.GID,
|
organizationID gid.GID,
|
||||||
) (*coredata.Session, *coredata.Membership, error) {
|
) (*coredata.Session, *coredata.Membership, error) {
|
||||||
var (
|
var (
|
||||||
now = time.Now()
|
now = time.Now()
|
||||||
rootSession = &coredata.Session{}
|
rootSession = &coredata.Session{}
|
||||||
identity = &coredata.Identity{}
|
identity = &coredata.Identity{}
|
||||||
membership = &coredata.Membership{}
|
membership = &coredata.Membership{}
|
||||||
scope = coredata.NewScopeFromObjectID(organizationID)
|
childSession = &coredata.Session{}
|
||||||
|
scope = coredata.NewScopeFromObjectID(organizationID)
|
||||||
)
|
)
|
||||||
|
|
||||||
err := s.pg.WithTx(
|
err := s.pg.WithTx(
|
||||||
@@ -365,7 +366,7 @@ func (s SessionService) OpenPasswordChildSessionForOrganization(
|
|||||||
}
|
}
|
||||||
|
|
||||||
tenantID := scope.GetTenantID()
|
tenantID := scope.GetTenantID()
|
||||||
childSession := &coredata.Session{
|
childSession = &coredata.Session{
|
||||||
ID: gid.New(tenantID, coredata.SessionEntityType),
|
ID: gid.New(tenantID, coredata.SessionEntityType),
|
||||||
IdentityID: rootSession.IdentityID,
|
IdentityID: rootSession.IdentityID,
|
||||||
TenantID: &tenantID,
|
TenantID: &tenantID,
|
||||||
@@ -398,7 +399,7 @@ func (s SessionService) OpenPasswordChildSessionForOrganization(
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootSession, membership, nil
|
return childSession, membership, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenSAMLChildSessionForOrganization creates a SAML-authenticated child session for the given
|
// OpenSAMLChildSessionForOrganization creates a SAML-authenticated child session for the given
|
||||||
@@ -535,7 +536,7 @@ func (s SessionService) AssumeOrganizationSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If child session already exists use it
|
// If child session already exists use it
|
||||||
if err := childSession.LoadByRootSessionIDAndMembershipID(ctx, tx, rootSession.IdentityID, membership.ID); err == nil {
|
if err := childSession.LoadByRootSessionIDAndMembershipID(ctx, tx, rootSession.ID, membership.ID); err == nil {
|
||||||
if childSession.ExpireReason == nil && now.Before(childSession.ExpiredAt) {
|
if childSession.ExpireReason == nil && now.Before(childSession.ExpiredAt) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -408,13 +408,13 @@ func (r *mutationResolver) SignIn(ctx context.Context, input types.SignInInput)
|
|||||||
|
|
||||||
if input.OrganizationID != nil {
|
if input.OrganizationID != nil {
|
||||||
var err error
|
var err error
|
||||||
session, _, err = r.iam.SessionService.OpenPasswordChildSessionForOrganization(ctx, session.ID, *input.OrganizationID)
|
_, _, err = r.iam.SessionService.OpenPasswordChildSessionForOrganization(ctx, session.ID, *input.OrganizationID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Here session middleware already took care of expired/nil root session so we only handle membership related errors
|
// Here session middleware already took care of expired/nil root session so we only handle membership related errors
|
||||||
var errMembershipNotFound *iam.ErrMembershipNotFound
|
var errMembershipNotFound *iam.ErrMembershipNotFound
|
||||||
var errMembershipInactive *iam.ErrMembershipInactive
|
var errMembershipInactive *iam.ErrMembershipInactive
|
||||||
|
|
||||||
if errors.As(err, errMembershipNotFound) || errors.As(err, errMembershipInactive) {
|
if errors.As(err, &errMembershipNotFound) || errors.As(err, &errMembershipInactive) {
|
||||||
return nil, gqlutils.Forbidden(ctx, err)
|
return nil, gqlutils.Forbidden(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user