aboutsummaryrefslogtreecommitdiff
path: root/Assistant/CredPairCache.hs
blob: 2b8f72e7cd6a9afaaa256694bc90c074852ba5dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
{- git-annex assistant CredPair cache.
 -
 - Copyright 2014 Joey Hess <joey@kitenet.net>
 -
 - Licensed under the GNU GPL version 3 or higher.
 -}

{-# LANGUAGE BangPatterns #-}

module Assistant.CredPairCache (
	cacheCred,
	getCachedCred,
	expireCachedCred,
) where

import Assistant.Types.CredPairCache
import Types.Creds
import Assistant.Common
import Utility.ThreadScheduler

import qualified Data.Map as M
import Control.Concurrent

{- Caches a CredPair, but only for a limited time, after which it
 - will expire.
 -
 - Note that repeatedly caching the same CredPair
 - does not reset its expiry time.
 -}
cacheCred :: CredPair -> Seconds -> Assistant ()
cacheCred (login, password) expireafter = do
	cache <- getAssistant credPairCache
	liftIO $ do
		changeStrict cache $ M.insert login password
		void $ forkIO $ do
			threadDelaySeconds expireafter
			changeStrict cache $ M.delete login

getCachedCred :: Login -> Assistant (Maybe Password)
getCachedCred login = do
	cache <- getAssistant credPairCache
	liftIO $ M.lookup login <$> readMVar cache

expireCachedCred :: Login -> Assistant ()
expireCachedCred login = do
	cache <- getAssistant credPairCache
	liftIO $ changeStrict cache $ M.delete login

{- Update map strictly to avoid keeping references to old creds in memory. -}
changeStrict :: CredPairCache -> (M.Map Login Password -> M.Map Login Password) -> IO ()
changeStrict cache a = modifyMVar_ cache $ \m -> do
	let !m' = a m
	return m'