-- SPDX-FileCopyrightText: 2022-24 Gregor Kleen ,Steffen Jost ,Steffen Jost -- -- 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