1 module Rakka.Authorization
11 import qualified Codec.Binary.UTF8.String as UTF8
12 import Control.Concurrent.STM
14 import Control.Monad.Trans
15 import qualified Data.ByteString as B
17 import qualified Data.Map as M hiding (Map)
19 import OpenSSL.EVP.Base64
20 import OpenSSL.EVP.Digest
21 import Rakka.SystemConfig
22 import System.Directory
23 import System.FilePath
29 adbFilePath :: !FilePath
30 , adbUserMap :: !(TVar UserMap)
31 , adbSyncRequest :: !(TVar Bool)
35 type UserMap = Map String String
38 mkAuthDB :: FilePath -> IO AuthDB
40 = do let path = lsdir </> "authDB"
41 m <- newTVarIO =<< loadUserMap path
42 req <- newTVarIO False
46 , adbSyncRequest = req
50 isValidPair :: MonadIO m => AuthDB -> String -> String -> m Bool
51 isValidPair adb name pass
52 = liftIO $ do sha1 <- return . fromJust =<< getDigestByName "SHA1"
53 let hash = digestBS sha1 $ B.pack $ UTF8.encode pass
54 atomically $ do m <- readTVar (adbUserMap adb)
55 return (M.lookup name m == Just hash)
58 getUserList :: MonadIO m => AuthDB -> m [String]
62 do m <- readTVar (adbUserMap adb)
66 addUser :: MonadIO m => AuthDB -> String -> String -> m ()
69 do sha1 <- return . fromJust =<< getDigestByName "SHA1"
70 let hash = digestBS sha1 $ B.pack $ UTF8.encode pass
71 m <- atomically $ do m <- readTVar (adbUserMap adb)
72 let m' = M.insert name hash m
73 writeTVar (adbUserMap adb) m'
75 saveUserMap (adbFilePath adb) m
78 delUser :: MonadIO m => AuthDB -> String -> m ()
81 do m <- atomically $ do m <- readTVar (adbUserMap adb)
82 let m' = M.delete name m
83 writeTVar (adbUserMap adb) m'
85 saveUserMap (adbFilePath adb) m
88 loadUserMap :: FilePath -> IO UserMap
90 = do exist <- doesFileExist path
92 liftM (M.fromList . map decodePair . fromJust . deserializeStringPairs)
96 sha1 <- return . fromJust =<< getDigestByName "SHA1"
97 return (initMap sha1 m)
99 decodePair :: (String, String) -> (String, String)
100 decodePair (name, b64Hash)
101 = (UTF8.decodeString name, decodeBase64 b64Hash)
103 initMap :: Digest -> UserMap -> UserMap
105 | M.null m = let name = "root"
106 hash = digest sha1 ""
108 M.singleton name hash
112 saveUserMap :: FilePath -> UserMap -> IO ()
114 = writeFile path $ serializeStringPairs $ map encodePair $ M.toList m
116 encodePair :: (String, String) -> (String, String)
117 encodePair (name, hash)
118 = (UTF8.encodeString name, encodeBase64 hash)