@@ -5,17 +5,17 @@ import { DateTime } from 'luxon'
55import { ItemRepo } from '../Data/ItemRepository'
66import { RequestService , userTokens } from '../Data/Requests'
77import { IClipboardItem , isImageContent , isRTFContent , isTextContent , RemoteItemStatus } from '../DataModels/DataTypes'
8- import { IAppState , IKeyboardEvent , IMouseEvent , IReceiveChannel } from '../DataModels/LocalTypes'
8+ import { IAppState , IKeyboardEvent , IMouseEvent , IReceiveChannel , ISavedUser } from '../DataModels/LocalTypes'
99import { CryptoService } from '../Utils/CryptoService'
1010import { JsUtil } from '../Utils/JsUtil'
1111import { AppSettings } from './AppSettings'
1212import { messages } from './CommunicationMessages'
13- import { InitUserSettings , IUserPreferences , store , userPreferences } from './UserPreferences'
13+ import { clearUserData , getUserData , InitUserSettings , IUserPreferences , store , storeUserData , userPreferences } from './UserPreferences'
1414
1515const shortcutsKey = `fileclip.shortcuts`
1616
1717export const state : IAppState = {
18- pullInterval : undefined ,
18+ clipboardPullInterval : undefined ,
1919 remoteSyncInterval : undefined ,
2020 user : undefined ,
2121 lastHash : ''
@@ -41,7 +41,7 @@ async function saveJSONFile(data: object) {
4141let cleanUpInterval : NodeJS . Timer | undefined = undefined
4242
4343export const handleCleanUpParameterChange = async ( ) => {
44- console . log ( " CLEANUP CALLED" )
44+ console . log ( ' CLEANUP CALLED' )
4545 if ( cleanUpInterval ) {
4646 clearInterval ( cleanUpInterval )
4747 }
@@ -81,9 +81,9 @@ export const actionsExported = {
8181 } ,
8282 sendSettings : ( settings : IUserPreferences ) => actions . sendFrontendNotification ( channelsToRender . setSettings , JSON . stringify ( settings ) ) ,
8383 clearSyncInterval : ( ) => {
84- console . log ( " remote sync stopped!" )
84+ console . log ( ' remote sync stopped!' )
8585 clearInterval ( state . remoteSyncInterval )
86- state . remoteSyncInterval = undefined ;
86+ state . remoteSyncInterval = undefined
8787 } ,
8888 async startRemoteSync ( interval : number ) {
8989 if ( state . remoteSyncInterval ) return
@@ -100,7 +100,14 @@ export const actionsExported = {
100100 await ItemRepo . initialLoadItems ( state . user . masterKey as string )
101101 state . remoteSyncInterval = setInterval ( sync , interval )
102102 } ,
103- askPassword : async ( ) => localMainWindow . webContents . send ( channelsToRender . askPassword , true ) ,
103+ askPassword : async ( ) => {
104+ const saved = getUserData ( 'savedUser' )
105+ if ( saved ) {
106+ localMainWindow . webContents . send ( channelsToRender . askPassword , true )
107+ } else {
108+ localMainWindow . webContents . send ( channelsToRender . askPassword , false )
109+ }
110+ } ,
104111 openWindow : async ( window : string ) => localMainWindow . webContents . send ( channelsToRender . openWindow , window )
105112}
106113
@@ -118,8 +125,8 @@ const actions = {
118125 localMainWindow . webContents . send ( channelsToRender . loadItems , itemList )
119126 } ,
120127 async startClipboardPooling ( ) {
121- if ( state . pullInterval ) return
122- state . pullInterval = setInterval ( async ( ) => await actions . TrySaveClipboard ( 10 ) , 200 )
128+ if ( state . clipboardPullInterval ) return
129+ state . clipboardPullInterval = setInterval ( async ( ) => await actions . TrySaveClipboard ( 10 ) , 200 )
123130 } ,
124131 async writeToClipboard ( hash : string ) {
125132 const result = items ( ) ?. get ( hash )
@@ -197,9 +204,11 @@ const actions = {
197204 logout : ( ) => {
198205 RequestService . account . logout ( )
199206 actionsExported . clearSyncInterval ( )
207+ clearInterval ( state . clipboardPullInterval )
200208 ItemRepo . reset ( )
201209 actions . sendItems ( ItemRepo . getAll ( ) )
202210 state . user = undefined
211+ clearUserData ( 'savedUser' )
203212 actionsExported . askPassword ( )
204213 } ,
205214 sendFrontendNotification : ( notification : typeof channelsToRender [ keyof typeof channelsToRender ] , ...args : any [ ] ) => {
@@ -229,48 +238,77 @@ const ioHookChannels: IReceiveChannel[] = [
229238 }
230239]
231240
232- async function loginUser ( rawUser : { name : string , password : string , code : string } ) {
241+ async function loginUser ( rawUser : { name : string ; password : string ; code : string ; wasRemembered : boolean ; rememberLogin : boolean } ) {
233242 try {
234- const localUser = CryptoService . HashUserLocal ( rawUser )
235- state . user = localUser
243+ if ( rawUser . wasRemembered ) {
244+ const data = JSON . parse ( getUserData ( 'savedUser' ) ) as ISavedUser
245+ const localUser = CryptoService . HashUserLocal ( { name : data . name , password : rawUser . password } )
246+ try {
247+ const refresh = CryptoService . DecryptText ( data . refresh , localUser . masterKey )
248+ userTokens . refresh = refresh
249+ console . log ( refresh )
250+ } catch ( error ) {
251+ actionsExported . alertFrontend ( 'password incorrect!' )
252+ return
253+ }
254+ state . user = localUser
255+ // TODO add retries
256+ const refreshRes = await RequestService . account . refresh ( )
257+ if ( refreshRes . ok && refreshRes . data ) {
258+ userTokens . access_expires = DateTime . now ( ) . plus ( { minutes : 55 } )
259+ userTokens . access = refreshRes . data . access_token
260+ } else {
261+ actionsExported . alertFrontend ( 'failed refresh the token. please try to log in again.' )
262+ actions . logout ( )
263+ }
264+ } else {
265+ const localUser = CryptoService . HashUserLocal ( rawUser )
266+ state . user = localUser
236267
237- const loginRes = await RequestService . account . login ( localUser . name , localUser . remotePassword , rawUser . code )
268+ const loginRes = await RequestService . account . login ( localUser . name , localUser . remotePassword , rawUser . code )
238269
239- if ( loginRes . code === 206 ) {
240- if ( loginRes . data ) {
241- localMainWindow . webContents . send ( channelsToRender . confirmTotp , loginRes . data )
270+ if ( loginRes . code === 206 ) {
271+ if ( loginRes . data ) {
272+ localMainWindow . webContents . send ( channelsToRender . confirmTotp , loginRes . data )
273+ }
274+ return
275+ }
276+ if ( loginRes . code === 400 ) {
277+ actionsExported . alertFrontend ( '2fa code incorrect!' )
278+ return
279+ }
280+ if ( loginRes . ok && loginRes . data ) {
281+ userTokens . access_expires = DateTime . now ( ) . plus ( { minutes : 55 } )
282+ userTokens . access = loginRes . data . access_token
283+ userTokens . refresh = loginRes . data . refresh_token
284+ if ( rawUser . rememberLogin ) {
285+ const saved : ISavedUser = {
286+ refresh : CryptoService . EncryptText ( userTokens . refresh , state . user . masterKey as string ) ,
287+ name : localUser . name
288+ }
289+ storeUserData ( 'savedUser' , JSON . stringify ( saved ) )
290+ }
291+ } else {
292+ actionsExported . alertFrontend ( 'password incorrect!' )
242293 }
243- return
244- }
245- if ( loginRes . code === 400 )
246- {
247- actionsExported . alertFrontend ( "2fa code incorrect!" )
248- return
249294 }
250- if ( loginRes . ok && loginRes . data ) {
251- userTokens . access_expires = DateTime . now ( ) . plus ( { minutes : 55 } )
252- userTokens . access = loginRes . data . access_token
253- userTokens . refresh = loginRes . data . refresh_token
254295
255- actions . startClipboardPooling ( )
256- if ( userPreferences . enableRemoteSync . value ) {
257- actionsExported . startRemoteSync ( userPreferences . remoteSyncInterval . value * 1000 )
258- }
259- actionsExported . sendCurrentItems ( )
260- actionsExported . sendSettings ( userPreferences )
261- actions . sendShortcuts ( )
262- actions . sendFrontendNotification ( channelsToRender . passwordConfirmed )
263- } else {
264- // actions.sendFrontendNotification(channelsToRender.passwordIncorrect)
265- actionsExported . alertFrontend ( "password incorrect!" )
296+ actions . startClipboardPooling ( )
297+ if ( userPreferences . enableRemoteSync . value ) {
298+ actionsExported . startRemoteSync ( userPreferences . remoteSyncInterval . value * 1000 )
266299 }
300+ actionsExported . sendCurrentItems ( )
301+ actionsExported . sendSettings ( userPreferences )
302+ actions . sendShortcuts ( )
303+ actions . sendFrontendNotification ( channelsToRender . passwordConfirmed )
304+ console . log ( 'end of flow' )
267305 } catch ( e : any ) {
268306 actionsExported . alertFrontend ( e . toString ( ) )
269307 console . log ( e )
270308 }
271309}
272310
273- async function registerUser ( rawUser : { name : string , password : string } ) {
311+ async function registerUser ( rawUser : { name : string ; password : string } ) {
274312 try {
275313 const localUser = CryptoService . HashUserLocal ( rawUser )
276314 state . user = localUser
@@ -308,7 +346,7 @@ const channelsFromRender: IReceiveChannel[] = [
308346 {
309347 name : 'to.backend.get.shortcuts' ,
310348 handler : ( ) => {
311- console . log ( " got shortcuts" )
349+ console . log ( ' got shortcuts' )
312350 actions . sendShortcuts ( )
313351 }
314352 } ,
@@ -344,7 +382,7 @@ const channelsFromRender: IReceiveChannel[] = [
344382 name : 'to.backend.text.paste' ,
345383 handler : async ( event : IpcMainEvent , text : string ) => {
346384 localClipboard . writeText ( text )
347- actionsExported . alertFrontend ( " copied!" )
385+ actionsExported . alertFrontend ( ' copied!' )
348386 }
349387 } ,
350388 {
@@ -413,7 +451,11 @@ const channelsFromRender: IReceiveChannel[] = [
413451 if ( resDeleteItems . ok && resDeleteAccount . ok ) {
414452 actionsExported . alertFrontend ( messages ( ) . accountAndDataDeleted . ok )
415453 } else {
416- actionsExported . alertFrontend ( `${ messages ( ) . dataDeleted . fail } .\n\nAccount deletion code: ${ resDeleteAccount . code } .\nData deletion code: ${ resDeleteItems . code } ` )
454+ actionsExported . alertFrontend (
455+ `${ messages ( ) . dataDeleted . fail } .\n\nAccount deletion code: ${ resDeleteAccount . code } .\nData deletion code: ${
456+ resDeleteItems . code
457+ } `
458+ )
417459 }
418460 }
419461 } ,
@@ -430,13 +472,19 @@ const channelsFromRender: IReceiveChannel[] = [
430472 handler : async ( event : any , code : string , token : string ) => {
431473 const res = await RequestService . account . confirm2fa ( code , token )
432474 if ( res . ok ) {
433- actionsExported . alertFrontend ( " 2FA successfully enabled! Try logging in" )
434- actionsExported . openWindow ( " login" )
475+ actionsExported . alertFrontend ( ' 2FA successfully enabled! Try logging in' )
476+ actionsExported . openWindow ( ' login' )
435477 } else {
436478 actionsExported . alertFrontend ( `failed enabling 2FA. Code ${ res . code } ` )
437479 }
438480 }
439481 } ,
482+ {
483+ name : 'to.backend.frontendHandler.isReady' ,
484+ handler : async ( event : any ) => {
485+ actionsExported . askPassword ( )
486+ }
487+ }
440488]
441489
442490/**
@@ -454,7 +502,7 @@ export const channelsToRender = {
454502 alert : 'to.renderer.alert' ,
455503 openWindow : 'to.renderer.open.window' ,
456504 log : 'to.renderer.log' ,
457- confirmTotp : 'to.renderer.confirm.totp' ,
505+ confirmTotp : 'to.renderer.confirm.totp'
458506} as const
459507
460508let localClipboard : Clipboard
0 commit comments