module Gargantext.API.Server.Named.Public ( serverPublicGargAPI ) where import Control.Lens ((^?), _Just) import Data.List qualified as List import Data.Map.Strict qualified as Map import Data.Set qualified as Set import Gargantext.API.Node.File (fileApi) import Gargantext.API.Prelude (serverError, IsGargServer) import Gargantext.API.Public.Types (PublicData(..)) import Gargantext.API.Routes.Named.File qualified as Named import Gargantext.API.Routes.Named.Public qualified as Named import Gargantext.Core.Utils.DateUtils (utc2year) import Gargantext.Database.Admin.Types.Hyperdata.Corpus ( hc_fields ) import Gargantext.Database.Admin.Types.Hyperdata.CorpusField import Gargantext.Database.Admin.Types.Hyperdata.Folder ( HyperdataFolder ) import Gargantext.Database.Admin.Types.Node ( NodeId(..), Node, unNodeId ) import Gargantext.Database.Prelude (DBCmd, DBCmdExtra) import Gargantext.Database.Query.Table.Node.Error (HasNodeError(..)) import Gargantext.Database.Query.Table.NodeNode (selectPublicNodes) import Gargantext.Database.Schema.Node ( NodePoly(..), node_date, node_hyperdata ) -- (NodePoly(..)) import Gargantext.Prelude import Servant import Servant.Server.Generic (AsServerT) serverPublicGargAPI :: IsGargServer env err m => Text -> Named.GargPublicAPI (AsServerT m) serverPublicGargAPI baseUrl = Named.GargPublicAPI $ Named.GargPublicAPI' { publicHomeAPI = api_home baseUrl , publicNodeAPI = Named.NodeAPI api_node } api_home :: IsGargServer env err m => Text -> Named.HomeAPI (AsServerT m) api_home baseUrl = Named.HomeAPI $ catMaybes <$> map (toPublicData baseUrl) <$> filterPublicDatas <$> selectPublic api_node :: IsGargServer env err m => NodeId -> Named.FileAPI (AsServerT m) api_node nId = Named.FileAPI $ do pubNodes <- publicNodes -- TODO optimize with SQL case Set.member nId pubNodes of False -> serverError $ err405 { errBody = "Not allowed" } True -> fileApi nId ------------------------------------------------------------------------- selectPublic :: HasNodeError err => DBCmd err [( Node HyperdataFolder, Maybe Int)] selectPublic = selectPublicNodes -- For tests only -- pure $ replicate 6 defaultPublicData filterPublicDatas :: [(Node HyperdataFolder, Maybe Int)] -> [(Node HyperdataFolder, [NodeId])] filterPublicDatas datas = map (\(n,mi) -> let mi' = UnsafeMkNodeId <$> mi in ( _node_id n, (n, maybe [] (:[]) mi' )) ) datas & Map.fromListWith (\(n1,i1) (_n2,i2) -> (n1, i1 <> i2)) & Map.filter (not . null . snd) & Map.elems publicNodes :: HasNodeError err => DBCmdExtra err (Set NodeId) publicNodes = do candidates <- filterPublicDatas <$> selectPublicNodes pure $ Set.fromList $ List.concat $ map (\(n, ns) -> (_node_id n) : ns) candidates -- http://localhost:8008/api/v1.0/node/23543/file/download -- http://localhost:8000/images/Gargantextuel-212x300.jpg toPublicData :: Text -> (Node HyperdataFolder, [NodeId]) -> Maybe PublicData toPublicData base (n , mn) = do title <- (hd ^? (_Just . hf_data . cf_title)) abstract <- (hd ^? (_Just . hf_data . cf_desc )) img <- (Just $ url' mn) -- "images/Gargantextuel-212x300.jpg" url <- (Just $ url' mn) date <- Just (show $ utc2year (n^.node_date)) database <- (hd ^? (_Just . hf_data . cf_query)) author <- (hd ^? (_Just . hf_data . cf_authors)) pure $ PublicData { .. } where hd = head $ filter (\(HyperdataField cd _ _) -> cd == JSON) $ n^. (node_hyperdata . hc_fields) url' :: [NodeId] -> Text url' mn' = base <> "/public/" <> (show $ (maybe 0 unNodeId $ head mn')) <> "/file/download"