1
0
Эх сурвалжийг харах

enhance(ui): integrate new login component and refresh token handling

charlie 6 өдөр өмнө
parent
commit
e8cf21d594

+ 2 - 1
packages/ui/src/amplify/core.ts

@@ -18,7 +18,8 @@ export function init({ lang, authCognito }: any) {
   Amplify.configure({
     Auth: {
       Cognito: {
-        ...authCognito, loginWith: { email: true }
+        ...authCognito,
+        loginWith: { email: true }
       }
     }
   })

+ 1 - 1
packages/ui/src/amplify/index.ts

@@ -4,5 +4,5 @@ import { LSAuthenticator } from './ui'
 
 export {
   init, Auth,
-  LSAuthenticator,
+  LSAuthenticator
 }

+ 12 - 5
packages/ui/src/amplify/ui.tsx

@@ -119,11 +119,18 @@ export function LoginForm() {
   const loadSession = async () => {
     try {
       const ret = await Auth.fetchAuthSession()
-      console.log(ret)
       if (!ret?.userSub) throw new Error('no session')
       const user = await Auth.getCurrentUser()
       onSessionCallback?.({ ...ret, user })
-      setSessionUser(user)
+      const tokens = ret.tokens
+      setSessionUser({
+        ...user, signInUserSession: {
+          idToken: { jwtToken: tokens?.idToken?.toString() },
+          accessToken: { jwtToken: tokens?.accessToken.toString() },
+          refreshToken: null
+        }
+      })
+      await (new Promise(resolve => setTimeout(resolve, 100)))
     } catch (e) {
       console.warn('no current session:', e)
       setSessionUser(false)
@@ -194,7 +201,7 @@ export function LoginForm() {
             return
           case 'DONE':
             // signed in
-            loadSession()
+            await loadSession()
             return
           default:
             throw new Error('Unsupported sign-in step: ' + nextStep)
@@ -206,8 +213,8 @@ export function LoginForm() {
         setLoading(false)
       }
     }}>
-      <InputRow id="email" type="text" name="email" label={t('Email')}/>
-      <InputRow id="password" type="password" name="password" label={t('Password')}/>
+      <InputRow id="email" type="text" required={true} name="email" autoFocus={true} label={t('Email')}/>
+      <InputRow id="password" type="password" required={true} name="password" label={t('Password')}/>
 
       <div className={'w-full'}>
         <Button type="submit" disabled={loading} className={'w-full'}>

+ 24 - 47
src/main/frontend/components/user/login.cljs

@@ -17,24 +17,24 @@
 
 (defn sign-out!
   []
-  (try (.signOut js/LSAmplify.Auth)
+  (try (.signOut js/LSAuth.Auth)
        (catch :default e (js/console.warn e))))
 
-(defn- setup-configure!
+(defn setup-configure!
   []
   #_:clj-kondo/ignore
-  (def setupAuthConfigure! (.-setupAuthConfigure js/LSAmplify))
+  (defn setupAuthConfigure! [config]
+    (.init js/LSAuth (bean/->js {:authCognito (merge config {:loginWith {:email true}})})))
   #_:clj-kondo/ignore
   (def LSAuthenticator
-    (adapt-class (.-LSAuthenticator js/LSAmplify)))
+    (adapt-class (.-LSAuthenticator js/LSAuth)))
 
-  (.setLanguage js/LSAmplify.I18n (or (:preferred-language @state/state) "en"))
   (setupAuthConfigure!
-   #js {:region              config/REGION,
-        :userPoolId          config/USER-POOL-ID,
-        :userPoolWebClientId config/COGNITO-CLIENT-ID,
-        :identityPoolId      config/IDENTITY-POOL-ID,
-        :oauthDomain         config/OAUTH-DOMAIN}))
+   {:region config/REGION,
+    :userPoolId config/USER-POOL-ID,
+    :userPoolClientId config/COGNITO-CLIENT-ID,
+    :identityPoolId config/IDENTITY-POOL-ID,
+    :oauthDomain config/OAUTH-DOMAIN}))
 
 (rum/defc user-pane
   [_sign-out! user]
@@ -55,45 +55,22 @@
 
 (rum/defc page-impl
   []
-  (let [[ready?, set-ready?] (rum/use-state false)
-        [tab, set-tab!] (rum/use-state :login)
-        *ref-el (rum/use-ref nil)]
-
-    (hooks/use-effect!
-     (fn [] (setup-configure!)
-       (set-ready? true)
-       (js/setTimeout
-        (fn []
-          (when-let [^js el (some-> (rum/deref *ref-el) (.querySelector ".amplify-tabs"))]
-            (let [btn1 (.querySelector el "button")]
-              (.addEventListener el "pointerdown"
-                                 (fn [^js e]
-                                   (if (= (.-target e) btn1)
-                                     (set-tab! :login)
-                                     (set-tab! :create-account)))))))))
-     [])
-
-    (hooks/use-effect!
-     (fn []
-       (when-let [^js el (rum/deref *ref-el)]
-         (js/setTimeout
-          #(some-> (.querySelector el (str "input[name=" (if (= tab :login) "username" "email") "]"))
-                   (.focus)) 100)))
-     [tab])
+  (let [*ref-el (rum/use-ref nil)]
 
     [:div.cp__user-login
      {:ref *ref-el}
-     (when ready?
-       (LSAuthenticator
-        {:termsLink "https://blog.logseq.com/terms/"}
-        (fn [^js op]
-          (let [sign-out!'      (.-signOut op)
-                ^js user-proxy (.-user op)
-                ^js user       (try (js/JSON.parse (js/JSON.stringify user-proxy))
-                                    (catch js/Error e
-                                      (js/console.error "Error: Amplify user payload:" e)))
-                user'          (bean/->clj user)]
-            (user-pane sign-out!' user')))))]))
+     (LSAuthenticator
+      {:titleRender (fn [tab]
+                      (shui/card-header
+                       {:class "px-0"}
+                       (shui/card-title
+                        {:class "capitalize"}
+                        (string/replace tab "-" " "))))
+       :onSessionCallback #()}
+      (fn [^js op]
+        (let [sign-out!' (.-signOut op)
+              user' (bean/->clj (.-sessionUser op))]
+          (user-pane sign-out!' user'))))]))
 
 (rum/defcs modal-inner <
   shortcut/disable-all-shortcuts
@@ -109,7 +86,7 @@
   (shui/dialog-open!
    (fn [_close] (modal-inner))
    {:label "user-login"
-    :content-props {:onPointerDownOutside #(let [inputs (sel "form[data-amplify-form] input:not([type=checkbox])")
+    :content-props {:onPointerDownOutside #(let [inputs (sel ".ls-authenticator-content form input:not([type=checkbox])")
                                                  inputs (some->> inputs (map (fn [^js e] (.-value e))) (remove string/blank?))]
                                              (when (seq inputs)
                                                (.preventDefault %)))}}))

+ 3 - 116
src/main/frontend/components/user/login.css

@@ -1,126 +1,13 @@
-.cp__user-login {
-  [data-amplify-authenticator] [data-amplify-router] {
-    --amplify-components-authenticator-router-background-color: var(--ls-primary-background-color);
-    --amplify-components-field-label-color: var(--ls-primary-text-color);
-    --amplify-components-authenticator-router-border-color: var(--ls-border-color);
-    --amplify-components-tabs-item-color: var(--ls-primary-text-color);
-    --amplify-components-tabs-item-active-color: var(--ls-primary-text-color);
-    --amplify-components-tabs-item-hover-color: var(--ls-primary-text-color);
-    --amplify-components-tabs-item-active-border-color: var(--ls-tertiary-background-color);
-    --amplify-components-tabs-border-width: 0;
-    --amplify-components-authenticator-state-inactive-background-color: var(--ls-tertiary-background-color);
-    --amplify-components-tabs-item-active-background-color: var(--ls-primary-background-color);
-    --amplify-components-button-border-color: var(--ls-border-color);
-    --amplify-components-textfield-border-color: var(--ls-border-color);
-    --amplify-components-button-primary-background-color: var(--color-indigo-600);
-    --amplify-components-text-color: var(--ls-primary-text-color);
-    --amplify-components-button-hover-background-color: var(--ls-primary-background-color);
-    --amplify-components-button-border-width: 0;
-    --amplify-internal-button-loading-background-color: var(--ls-header-button-background);
-    --amplify-components-authenticator-router-border-width: 1px;
-    --amplify-components-button-color: var(--ls-primary-text-color);
-    --amplify-components-divider-label-background-color: var(--ls-primary-background-color);
-    --amplify-components-divider-label-color: var(--ls-primary-text-color);
-    --amplify-components-heading-color: var(--ls-primary-text-color);
-    --amplify-components-button-link-hover-background-color: transparent;
-    --amplify-components-button-link-active-background-color: transparent;
-    --amplify-components-textfield-color: var(--ls-primary-text-color);
-    --amplify-components-checkbox-icon-background-color: var(--color-indigo-600);
-  }
-
-  [data-amplify-authenticator] [data-amplify-router] {
-    @apply overflow-hidden rounded-[6px] shadow-2xl;
-  }
-
-  [data-amplify-authenticator] [data-amplify-container] {
-    place-self: unset;
-  }
-
-  [data-amplify-authenticator] [data-amplify-form] {
-    @apply px-4 py-2;
-
-    @screen sm {
-      @apply px-6 py-4;
-    }
-  }
-}
-
-@media (min-width: 30rem) {
-  [data-amplify-authenticator] [data-amplify-container] {
-    width: 100%;
-  }
-}
+.cp__user-login {}
 
 .ui__dialog-content[label=user-login] {
-  @apply flex items-center top-0 p-0 border-none w-auto;
+  @apply flex items-center top-0 px-6 pt-0 w-auto;
 
   .ui__dialog-main-content {
-    @apply p-0 min-w-fit relative max-w-[600px] sm:max-w-[90vw] sm:w-[500px];
+    @apply p-0 w-[70vw] relative max-w-[600px] sm:max-w-[80vw] sm:w-[450px];
   }
 
   .ui__modal-close-wrap {
     @apply z-10 top-[4px];
   }
 }
-
-.cp__user {
-  &-login {
-    ::placeholder {
-      color: var(--ls-primary-text-color);
-      opacity: .3;
-    }
-
-    [data-indicator-position=top] > .amplify-tabs-item {
-      margin-top: 0;
-    }
-
-    .amplify-tabs-item {
-      transition: none;
-
-      &:focus {
-        color: var(--ls-primary-text-color);
-      }
-
-      &:hover {
-        opacity: .9;
-      }
-    }
-
-    .amplify-field-group {
-      @apply relative;
-
-      .amplify-button {
-        color: var(--ls-primary-text-color);
-
-        &:active, &:hover, &:focus {
-          background-color: transparent;
-        }
-      }
-    }
-
-    .amplify-field-group__outer-end {
-      @apply absolute right-0 top-0 bottom-0;
-    }
-
-    .amplify-input {
-      border-radius: 4px !important;
-    }
-
-    .amplify-checkboxfield {
-      @apply text-sm;
-
-      .amplify-field__error-message {
-        color: var(--ls-primary-text-color);
-        opacity: .4;
-      }
-    }
-
-    .amplify-text--error {
-      color: var(--ls-error-text-color);
-    }
-  }
-}
-
-.federated-sign-in-container {
-  display: none;
-}

+ 2 - 0
src/main/frontend/handler.cljs

@@ -8,6 +8,7 @@
             [frontend.components.content :as cp-content]
             [frontend.components.editor :as editor]
             [frontend.components.page :as page]
+            [frontend.components.user.login :as user.login]
             [frontend.components.reference :as reference]
             [frontend.components.whiteboard :as whiteboard]
             [frontend.config :as config]
@@ -143,6 +144,7 @@
 
   (register-components-fns!)
   (user-handler/restore-tokens-from-localstorage)
+  (user.login/setup-configure!)
   (state/set-db-restoring! true)
   (when (util/electron?)
     (el/listen!))

+ 15 - 0
src/main/frontend/handler/user.cljs

@@ -108,6 +108,20 @@
       (when (string/starts-with? key prefix)
         (js/localStorage.removeItem key)))))
 
+(defn auto-fill-refresh-token-from-cognito!
+  []
+  (let [prefix "CognitoIdentityServiceProvider."
+        refresh-token-key (some #(when (string/starts-with? % prefix)
+                                   (when (string/ends-with? % "refreshToken")
+                                     %))
+                                (js/Object.keys js/localStorage))]
+    (when refresh-token-key
+      (let [refresh-token (js/localStorage.getItem refresh-token-key)]
+        (when (and refresh-token (not= refresh-token "undefined"))
+          (state/set-auth-refresh-token refresh-token)
+          (js/localStorage.setItem "refresh-token" refresh-token)))))
+  )
+
 (defn- clear-tokens
   ([]
    (state/set-auth-id-token nil)
@@ -206,6 +220,7 @@
    (:jwtToken (:idToken session))
    (:jwtToken (:accessToken session))
    (:token (:refreshToken session)))
+  (auto-fill-refresh-token-from-cognito!)
   (state/pub-event! [:user/fetch-info-and-graphs]))
 
 (defn ^:export login-with-username-password-e2e