Skip to content
Snippets Groups Projects
Commit 2511c52d authored by stuebinm's avatar stuebinm
Browse files

make link adjustments configurable

this allows for creating custom URI "schemas" in the linter's config,
which may be either allowed, prefixed, or translated according to
some (domain-based) substitution.
parent 321f4d5f
No related branches found
No related tags found
No related merge requests found
...@@ -4,7 +4,19 @@ ...@@ -4,7 +4,19 @@
"AllowScripts":true, "AllowScripts":true,
"MaxLintLevel":"Fatal", "MaxLintLevel":"Fatal",
"DontCopyAssets":true, "DontCopyAssets":true,
"LinkPrefix":"https://exit.rc3.world?link=", "UriSchemas": {
"AllowedDomains":["example.org"], "https" : {
"BlockedDomains":[] "scope" : ["website"],
"allowed" : ["example.org"],
"blocked" : ["blocked.com"],
"prefix" : "https://ausgang.rc3.world?link="
},
"world" : {
"scope" : ["map"],
"substs" : {
"lounge" : "/@/lalala",
"lobby" : "/@/lounge"
}
}
}
} }
...@@ -21,10 +21,10 @@ import Data.Text (Text) ...@@ -21,10 +21,10 @@ import Data.Text (Text)
import GHC.Generics (Generic (Rep, from, to), K1 (..), import GHC.Generics (Generic (Rep, from, to), K1 (..),
M1 (..), (:*:) (..)) M1 (..), (:*:) (..))
import Types (Level) import Types (Level)
import Uris (SchemaSet)
import WithCli (Proxy (..)) import WithCli (Proxy (..))
import WithCli.Pure (Argument (argumentType, parseArgument)) import WithCli.Pure (Argument (argumentType, parseArgument))
type family HKD f a where type family HKD f a where
HKD Identity a = a HKD Identity a = a
HKD f a = f a HKD f a = f a
...@@ -40,12 +40,7 @@ data LintConfig f = LintConfig ...@@ -40,12 +40,7 @@ data LintConfig f = LintConfig
-- ^ Don't copy map assets (mostly useful for development) -- ^ Don't copy map assets (mostly useful for development)
, configAllowScripts :: HKD f Bool , configAllowScripts :: HKD f Bool
-- ^ Allow defining custom scripts in maps -- ^ Allow defining custom scripts in maps
, configLinkPrefix :: HKD f Text , configUriSchemas :: HKD f SchemaSet
-- ^ prefix that will be added to all outgoing weblinks
, configAllowedDomains :: HKD f [Text]
-- ^ domains that are allowed in weblinks and will not be modified
, configBlockedDomains :: HKD f [Text]
-- ^ domains that are blocked; weblinks to these is an error
} deriving (Generic) } deriving (Generic)
type LintConfig' = LintConfig Identity type LintConfig' = LintConfig Identity
...@@ -57,6 +52,7 @@ deriving instance ...@@ -57,6 +52,7 @@ deriving instance
, Show (HKD a Level) , Show (HKD a Level)
, Show (HKD a [Text]) , Show (HKD a [Text])
, Show (HKD a Bool) , Show (HKD a Bool)
, Show (HKD a SchemaSet)
) )
=> Show (LintConfig a) => Show (LintConfig a)
...@@ -73,6 +69,7 @@ instance ...@@ -73,6 +69,7 @@ instance
, FromJSON (HKD a Text) , FromJSON (HKD a Text)
, FromJSON (HKD a Level) , FromJSON (HKD a Level)
, FromJSON (HKD a Bool) , FromJSON (HKD a Bool)
, FromJSON (HKD a SchemaSet)
) )
=> FromJSON (LintConfig a) => FromJSON (LintConfig a)
where where
......
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
-- | Paths are horrible, so they have their own module now. -- | Paths are horrible, so they have their own module now.
-- I just hope you are running this on some kind of Unix -- I just hope you are running this on some kind of Unix
module Paths where module Paths where
import Data.Text (Text) import Data.Text (Text, isPrefixOf)
import qualified Data.Text as T import qualified Data.Text as T
import System.FilePath (splitPath) import System.FilePath (splitPath)
import System.FilePath.Posix ((</>)) import System.FilePath.Posix ((</>))
...@@ -18,21 +19,17 @@ data RelPath = Path Int Text (Maybe Text) ...@@ -18,21 +19,17 @@ data RelPath = Path Int Text (Maybe Text)
deriving (Show, Eq, Ord) deriving (Show, Eq, Ord)
extractDomain :: Text -> Maybe Text
extractDomain url =
let (_,_,_,matches) = url =~ ("^https://([^/]+)/?.*$" :: Text) :: (Text,Text,Text,[Text])
in case matches of
[domain] -> Just domain
_ -> Nothing
data PathResult = OkRelPath RelPath | AbsolutePath | NotAPath | UnderscoreMapLink | AtMapLink
-- | horrible regex parsing for filepaths that is hopefully kinda safe -- | horrible regex parsing for filepaths that is hopefully kinda safe
parsePath :: Text -> Maybe RelPath parsePath :: Text -> PathResult
parsePath text = parsePath text =
if rest =~ ("^([^/]*[^\\./]/)*[^/]*[^\\./]$" :: Text) :: Bool if | rest =~ ("^([^/]*[^\\./]/)*[^/]*[^\\./]$" :: Text) -> OkRelPath (Path up path fragment)
then Just $ Path up path fragment | "/_/" `isPrefixOf` text -> UnderscoreMapLink
else Nothing | "/@/" `isPrefixOf` text -> AtMapLink
| "/" `isPrefixOf` text -> AbsolutePath
| otherwise -> NotAPath
where where
(_, prefix, rest, _) = (_, prefix, rest, _) =
text =~ ("^((\\.|\\.\\.)/)*" :: Text) :: (Text, Text, Text, [Text]) text =~ ("^((\\.|\\.\\.)/)*" :: Text) :: (Text, Text, Text, [Text])
......
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
-- | Contains checks for custom ties of the map json -- | Contains checks for custom ties of the map json
{-# LANGUAGE DataKinds #-}
module Properties (checkMap, checkTileset, checkLayer) where module Properties (checkMap, checkTileset, checkLayer) where
...@@ -15,13 +17,16 @@ import Tiled2 (HasProperties (adjustProperties, getProperties), ...@@ -15,13 +17,16 @@ import Tiled2 (HasProperties (adjustProperties, getProperties),
Tiledmap (..), Tileset (..)) Tiledmap (..), Tileset (..))
import Util (layerIsEmpty, prettyprint, showText) import Util (layerIsEmpty, prettyprint, showText)
import Data.Data (Proxy (Proxy))
import Data.Maybe (fromMaybe, isJust) import Data.Maybe (fromMaybe, isJust)
import GHC.TypeLits (KnownSymbol)
import LintConfig (LintConfig (..)) import LintConfig (LintConfig (..))
import LintWriter (LintWriter, adjust, askContext, askFileDepth, import LintWriter (LintWriter, adjust, askContext, askFileDepth,
complain, dependsOn, forbid, lintConfig, complain, dependsOn, forbid, lintConfig,
offersEntrypoint, suggest, warn) offersEntrypoint, suggest, warn)
import Paths (RelPath (..), parsePath, extractDomain) import Paths (PathResult (..), RelPath (..), parsePath)
import Types (Dep (Link, Local, LocalMap, MapLink)) import Types (Dep (Link, Local, LocalMap, MapLink))
import Uris (SubstError (..), applySubst)
-- | Checks an entire map for "general" lints. -- | Checks an entire map for "general" lints.
...@@ -172,22 +177,9 @@ checkLayerProperty p@(Property name _value) = case name of ...@@ -172,22 +177,9 @@ checkLayerProperty p@(Property name _value) = case name of
"openWebsite" -> do "openWebsite" -> do
uselessEmptyLayer uselessEmptyLayer
suggestProperty $ Property "openWebsiteTrigger" (StrProp "onaction") suggestProperty $ Property "openWebsiteTrigger" (StrProp "onaction")
unwrapLink p $ \link -> if "https://" `isPrefixOf` link unwrapURI (Proxy @"website") p
then do (dependsOn . Link)
config <- lintConfig id (dependsOn . Local)
case extractDomain link of
Just domain
| domain `elem` configBlockedDomains config
-> complain $ "domain " <> domain <> " is blocked."
| domain `elem` configAllowedDomains config
-> dependsOn $ Link link
| otherwise
-> do
dependsOn $ Link link
prefix <- lintConfig configLinkPrefix
setProperty "openWebsite" (prefix <> link)
Nothing -> complain "invalid link?"
else unwrapPath link (dependsOn . Local)
"openWebsiteTrigger" -> do "openWebsiteTrigger" -> do
isString p isString p
unlessHasProperty "openWebsiteTriggerMessage" unlessHasProperty "openWebsiteTriggerMessage"
...@@ -207,11 +199,9 @@ checkLayerProperty p@(Property name _value) = case name of ...@@ -207,11 +199,9 @@ checkLayerProperty p@(Property name _value) = case name of
"allowApi" -> isForbidden "allowApi" -> isForbidden
"exitUrl" -> do "exitUrl" -> do
forbidEmptyLayer forbidEmptyLayer
unwrapLink p $ \link -> if unwrapURI (Proxy @"map") p
| "/_/" `isPrefixOf` link -> (dependsOn . MapLink)
complain "absolute map links (i.e. links starting with '/_/') are disallowed." (dependsOn . LocalMap)
| "/@/" `isPrefixOf` link -> dependsOn $ MapLink link -- TODO
| otherwise -> unwrapPath link (dependsOn . LocalMap)
"exitSceneUrl" -> "exitSceneUrl" ->
deprecatedUseInstead "exitUrl" deprecatedUseInstead "exitUrl"
"exitInstance" -> "exitInstance" ->
...@@ -350,12 +340,15 @@ unwrapInt (Property name value) f = case value of ...@@ -350,12 +340,15 @@ unwrapInt (Property name value) f = case value of
unwrapPath :: Text -> (RelPath -> LintWriter a) -> LintWriter a unwrapPath :: Text -> (RelPath -> LintWriter a) -> LintWriter a
unwrapPath str f = case parsePath str of unwrapPath str f = case parsePath str of
Just p@(Path up _ _) -> do OkRelPath p@(Path up _ _) -> do
depth <- askFileDepth depth <- askFileDepth
if up <= depth if up <= depth
then f p then f p
else complain $ "cannot acess paths \"" <> str <> "\" which is outside your repository" else complain $ "cannot acess paths \"" <> str <> "\" which is outside your repository"
Nothing -> complain $ "path \"" <> str <> "\" is invalid" NotAPath -> complain $ "path \"" <> str <> "\" is invalid"
AbsolutePath -> complain "absolute paths are disallowed. Use world:// instead."
UnderscoreMapLink -> complain "map links using /_/ are disallowed. Use world:// instead."
AtMapLink -> complain "map links using /@/ are disallowed. Use world:// instead."
-- | just asserts that this is a string -- | just asserts that this is a string
isString :: Property -> LintWriter a isString :: Property -> LintWriter a
...@@ -369,3 +362,21 @@ isIntInRange :: Int -> Int -> Property -> LintWriter a ...@@ -369,3 +362,21 @@ isIntInRange :: Int -> Int -> Property -> LintWriter a
isIntInRange l r p@(Property name _) = unwrapInt p $ \int -> isIntInRange l r p@(Property name _) = unwrapInt p $ \int ->
if l < int && int < r then pure () if l < int && int < r then pure ()
else complain $ "Property " <> prettyprint name <> " should be between" <> showText l <> " and " <> showText r else complain $ "Property " <> prettyprint name <> " should be between" <> showText l <> " and " <> showText r
unwrapURI :: (KnownSymbol s, HasProperties a)
=> Proxy s -> Property -> (Text -> LintWriter a) -> (RelPath -> LintWriter a) -> LintWriter a
unwrapURI sym p@(Property name _) f g = unwrapLink p $ \link -> do
subst <- lintConfig configUriSchemas
case applySubst sym subst link of
Right uri -> do
setProperty name uri
f uri
Left NotALink -> unwrapPath link g
Left err -> complain $ case err of
IsBlocked -> link <> " is a blocked site."
InvalidLink -> link <> " is invalid."
SchemaDoesNotExist schema ->
"the URI schema " <> schema <> ":// does not exist."
WrongScope schema ->
"the URI schema " <> schema <> ":// cannot be used on \""<>name<>"\""
...@@ -35,6 +35,7 @@ library ...@@ -35,6 +35,7 @@ library
Util Util
Types Types
Paths Paths
Uris
LintConfig LintConfig
build-depends: base, build-depends: base,
aeson, aeson,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment