fradrive/src/Handler/Utils/Profile.hs

69 lines
2.9 KiB
Haskell

-- SPDX-FileCopyrightText: 2022-24 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
-- TODO: why is this Handler.Utils.Profile instead of Utils.Profile?
-- TODO: consider merging with Handler.Utils.Users?
module Handler.Utils.Profile
( module Utils.Mail
, module Utils.Postal
, validDisplayName, checkDisplayName, fixDisplayName
, validFraportPersonalNumber
) where
import Import.NoFoundation
import qualified Data.Text as Text
import qualified Data.MultiSet as MultiSet
import qualified Data.Set as Set
import Utils.Mail
import Utils.Postal
-- | remove last comma and swap order of the two parts, ie. transforming "surname, givennames" into "givennames surname".
-- Input "givennames surname" is left unchanged, except for removing excess whitespace
fixDisplayName :: UserDisplayName -> UserDisplayName
fixDisplayName udn =
let (Text.strip . Text.dropEnd 1 -> surname, Text.strip -> firstnames) = Text.breakOnEnd "," udn
in Text.toTitle $ Text.strip $ firstnames <> Text.cons ' ' surname
-- | Like `validDisplayName` but may return an automatically corrected name
checkDisplayName :: Maybe UserTitle -> UserFirstName -> UserSurname -> UserDisplayName -> Maybe UserDisplayName
checkDisplayName mTitle fName sName (fixDisplayName -> dName)
| validDisplayName mTitle fName sName dName = Just dName
| otherwise = Nothing
validDisplayName :: Maybe UserTitle
-> UserFirstName
-> UserSurname
-> UserDisplayName
-> Bool
validDisplayName (fmap stripFold -> mTitle) (stripFold -> fName) (stripFold -> sName) (stripFold -> dName)
= and [ dNameFrags `MultiSet.isSubsetOf` MultiSet.unions [titleFrags, fNameFrags, sNameFrags]
, sName `Text.isInfixOf` dName
, all ((<= 1) . Text.length) . filter (Text.any isAdd) $ Text.group dName
, dNameLetters `Set.isSubsetOf` Set.unions [titleLetters, fNameLetters, sNameLetters, addLetters]
]
where
titleFrags = foldMap makeMultiSet mTitle
dNameFrags = makeMultiSet dName
fNameFrags = makeMultiSet fName
sNameFrags = makeMultiSet sName
titleLetters = foldMap (Set.fromList . unpack) mTitle
fNameLetters = Set.fromList $ unpack fName
sNameLetters = Set.fromList $ unpack sName
dNameLetters = Set.fromList $ unpack dName
addLetters = Set.fromList [' ', '.', '-']
isAdd = (`Set.member` addLetters)
splitAdd = Text.split isAdd
makeMultiSet = MultiSet.fromList . filter (not . Text.null) . splitAdd
validFraportPersonalNumber :: Maybe Text -> Bool
validFraportPersonalNumber Nothing = False
validFraportPersonalNumber (Just t)
| (Just pn) <- readMay t
= pn >= (10000::Int) && pn <= (99999::Int) -- used to filter for SAP export
| otherwise = False