summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstuebinm2022-03-19 19:12:04 +0100
committerstuebinm2022-03-19 20:07:45 +0100
commitdbf2253dc4256809b255767cbf4ae9c236f18542 (patch)
treeae2eb6e09db7aeab76ef22171c43e679cfa2c86a
parent25111b467c91e411f1c7a4281c2eee5671db7406 (diff)
remove leftover rc3 things & some new stuff
this removes: - the bbb properties - all explicit mentions of rc3 - the weird script domain hacks (done via a substitution now) - some (few) of the weirder code choices it also adds some more type level witchery to deal with configs, which for some reason seems to be the hardest problem of this entire program … also the server now does inter-assembly dependency checking!
-rw-r--r--config.json16
-rw-r--r--lib/CheckMap.hs13
-rw-r--r--lib/LintConfig.hs163
-rw-r--r--lib/Properties.hs68
-rw-r--r--lib/Uris.hs90
-rw-r--r--server/Server.hs22
-rw-r--r--server/Worker.hs22
-rw-r--r--src/Main.hs9
-rw-r--r--src/Version.hs2
9 files changed, 222 insertions, 183 deletions
diff --git a/config.json b/config.json
index 1ccb0a5..35e89e9 100644
--- a/config.json
+++ b/config.json
@@ -6,13 +6,13 @@
"MaxLintLevel":"Fatal",
"DontCopyAssets":false,
"UriSchemas": {
- "world": {
- "scope" : ["map"],
- "substs" : {
- }
- },
- "https": {
- "scope" : [ "website", "audio" ]
- }
+ "https:": [
+ {
+ "scope" : [ "website", "audio" ]
+ },
+ {
+ "scope" : [ "script" ],
+ "allowed" : [ "scripts.world.di.c3voc.de" ]
+ }]
}
}
diff --git a/lib/CheckMap.hs b/lib/CheckMap.hs
index 9e3027c..8611f03 100644
--- a/lib/CheckMap.hs
+++ b/lib/CheckMap.hs
@@ -10,6 +10,7 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE RecordWildCards #-}
-- | Module that contains the high-level checking functions
module CheckMap (loadAndLintMap, MapResult(..), ResultKind(..), Optional,shrinkMapResult) where
@@ -28,7 +29,7 @@ import Badges (Badge)
import Data.Tiled (Layer (layerLayers, layerName),
Tiledmap (tiledmapLayers, tiledmapTilesets),
loadTiledmap)
-import LintConfig (LintConfig (configAssemblyTag), LintConfig')
+import LintConfig (LintConfig', LintConfig (..))
import LintWriter (LintResult, invertLintResult,
resultToAdjusted, resultToBadges,
resultToDeps, resultToLints, resultToOffers,
@@ -111,11 +112,12 @@ loadAndLintMap config path depth = loadTiledmap path <&> \case
-- | lint a loaded map
runLinter :: Bool -> LintConfig' -> Tiledmap -> Int -> MapResult Full
-runLinter isMain config tiledmap depth = MapResult
+runLinter isMain config@LintConfig{..} tiledmap depth = MapResult
{ mapresultLayer = invertThing layer
, mapresultTileset = invertThing tileset
, mapresultGeneral =
- ([Hint Error "main.json should link back to the lobby" | isMain && not (any linksLobby layerDeps)])
+ [Hint Warning "main.json should link back to the lobby"
+ | isMain && not (any linksLobby layerDeps)]
<> lintsToHints (resultToLints generalResult)
, mapresultDepends = resultToDeps generalResult
<> layerDeps
@@ -127,9 +129,10 @@ runLinter isMain config tiledmap depth = MapResult
}
where
linksLobby = \case
- MapLink link -> "/@/rc3_21/lobby" `T.isPrefixOf` link
+ MapLink link ->
+ ("/@/"<>configEventSlug<>"/lobby") `T.isPrefixOf` link
|| configAssemblyTag config == "lobby"
- _ -> False
+ _ -> False
layerDeps = concatMap resultToDeps layer
layer = checkLayerRec config depth (V.toList $ tiledmapLayers tiledmap)
tileset = checkThing tiledmapTilesets checkTileset
diff --git a/lib/LintConfig.hs b/lib/LintConfig.hs
index 11a8122..b0fa3b0 100644
--- a/lib/LintConfig.hs
+++ b/lib/LintConfig.hs
@@ -1,19 +1,21 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
-- | Module that deals with handling config options
-module LintConfig (LintConfig(..), LintConfig', patchConfig) where
+module LintConfig (LintConfig(..), LintConfig', ConfigKind (..), patchConfig,stuffConfig,feedConfig) where
import Universum
-import qualified Universum.Unsafe as Unsafe
import Data.Aeson (FromJSON (parseJSON), Options (..),
defaultOptions, eitherDecode)
@@ -28,38 +30,51 @@ import Uris (SchemaSet,
Substitution (DomainSubstitution))
import WithCli.Pure (Argument (argumentType, parseArgument))
-type family HKD f a where
- HKD Identity a = a
- HKD f a = f a
-data LintConfig f = LintConfig
- { configScriptInject :: HKD f (Maybe Text)
+
+data ConfigKind = Complete | Basic | Skeleton | Patch
+
+-- | a field that must be given in configs for both server & standalone linter
+type family ConfigField (f::ConfigKind) a where
+ ConfigField Patch a = Maybe a
+ ConfigField _ a = a
+
+-- | a field that must be given for the standalone linter, but not the server
+-- (usually because the server will infer them from its own config)
+type family StandaloneField (f :: ConfigKind) a where
+ StandaloneField Complete a = a
+ StandaloneField Skeleton a = a
+ StandaloneField _ a = Maybe a
+
+-- | a field specific to a single world / assembly
+type family WorldField (f :: ConfigKind) a where
+ WorldField Complete a = a
+ WorldField _ a = Maybe a
+
+data LintConfig (f :: ConfigKind) = LintConfig
+ { configScriptInject :: ConfigField f (Maybe Text)
-- ^ Link to Script that should be injected
- , configAssemblyTag :: HKD f Text
+ , configAssemblyTag :: WorldField f Text
-- ^ Assembly name (used for jitsiRoomAdminTag)
- , configAssemblies :: HKD f [Text]
+ , configAssemblies :: StandaloneField f [Text]
-- ^ list of all assembly slugs (used to lint e.g. world:// links)
- , configMaxLintLevel :: HKD f Level
+ , configEventSlug :: StandaloneField f Text
+ -- ^ slug of this event (used e.g. to resolve world:// links)
+ , configMaxLintLevel :: ConfigField f Level
-- ^ Maximum warn level allowed before the lint fails
- , configDontCopyAssets :: HKD f Bool
+ , configDontCopyAssets :: ConfigField f Bool
-- ^ Don't copy map assets (mostly useful for development)
- , configAllowScripts :: HKD f Bool
+ , configAllowScripts :: ConfigField f Bool
-- ^ Allow defining custom scripts in maps
- , configUriSchemas :: HKD f SchemaSet
+ , configUriSchemas :: ConfigField f SchemaSet
} deriving (Generic)
-type LintConfig' = LintConfig Identity
+type LintConfig' = LintConfig Complete
--- TODO: should probably find a way to write these constraints nicer ...
-deriving instance
- ( Show (HKD a (Maybe Text))
- , Show (HKD a Text)
- , Show (HKD a Level)
- , Show (HKD a [Text])
- , Show (HKD a Bool)
- , Show (HKD a SchemaSet)
- )
- => Show (LintConfig a)
+deriving instance Show (LintConfig Complete)
+deriving instance Show (LintConfig Skeleton)
+deriving instance Show (LintConfig Patch)
+instance NFData (LintConfig Basic)
aesonOptions :: Options
aesonOptions = defaultOptions
@@ -68,23 +83,13 @@ aesonOptions = defaultOptions
, fieldLabelModifier = drop 6
}
-instance
- ( FromJSON (HKD a (Maybe Text))
- , FromJSON (HKD a [Text])
- , FromJSON (HKD a Text)
- , FromJSON (HKD a Level)
- , FromJSON (HKD a Bool)
- , FromJSON (HKD a SchemaSet)
- )
- => FromJSON (LintConfig a)
- where
- parseJSON = genericParseJSON aesonOptions
+instance FromJSON (LintConfig Complete) where
+ parseJSON = genericParseJSON aesonOptions
--- need to define this one extra, since Aeson will not make
--- Maybe fields optional if the type isn't given explicitly.
---
--- Whoever said instances had confusing semantics?
-instance {-# Overlapping #-} FromJSON (LintConfig Maybe) where
+instance FromJSON (LintConfig Patch) where
+ parseJSON = genericParseJSON aesonOptions
+
+instance FromJSON (LintConfig Basic) where
parseJSON = genericParseJSON aesonOptions
@@ -118,30 +123,66 @@ instance GPatch i o
-- abstract, I just wanted to play around with higher kinded types for
-- a bit.
patch ::
- ( Generic (f Maybe)
- , Generic (f Identity)
- , GPatch (Rep (f Identity))
- (Rep (f Maybe))
+ ( Generic (f Patch)
+ , Generic (f Complete)
+ , GPatch (Rep (f Complete))
+ (Rep (f Patch))
)
- => f Identity
- -> f Maybe
- -> f Identity
+ => f Complete
+ -> f Patch
+ -> f Complete
patch x y = to (gappend (from x) (from y))
-patchConfig :: LintConfig Identity -> Maybe (LintConfig Maybe) -> LintConfig Identity
-patchConfig config p = config'
- { configUriSchemas = ("world", assemblysubsts) : configUriSchemas config'}
- where config' = case p of
- Just p -> patch config p
- Nothing -> config
- assemblysubsts =
- DomainSubstitution (M.fromList generated) scope
- where generated = (\slug -> (slug, "/@/rc3_21/"<>slug)) <$> configAssemblies config'
- scope = (\(DomainSubstitution _ s) -> s)
- . snd . Unsafe.head
- . filter ((==) "world" . fst)
- $ configUriSchemas config'
-
+patchConfig
+ :: LintConfig Complete
+ -> Maybe (LintConfig Patch)
+ -> LintConfig Complete
+patchConfig config p = expandWorlds config'
+ where
+ config' = case p of
+ Just p -> patch config p
+ Nothing -> config
+
+
+-- | feed a basic server config
+feedConfig
+ :: LintConfig Basic
+ -> [Text]
+ -> Text
+ -> LintConfig Skeleton
+feedConfig LintConfig{..} worlds eventslug = expandWorlds $
+ LintConfig
+ { configAssemblies = worlds
+ , configEventSlug = eventslug
+ , .. }
+
+-- | stuff a
+stuffConfig :: LintConfig Skeleton -> Text -> LintConfig Complete
+stuffConfig LintConfig{..} assemblyslug =
+ LintConfig
+ { configAssemblyTag = assemblyslug
+ , ..}
+
+class HasWorldList (a :: ConfigKind)
+instance HasWorldList 'Complete
+instance HasWorldList 'Skeleton
+
+-- kinda sad that ghc can't solve these contraints automatically,
+-- though i guess it also makes sense …
+expandWorlds
+ :: ( ConfigField a SchemaSet ~ SchemaSet
+ , StandaloneField a [Text] ~ [Text]
+ , StandaloneField a Text ~ Text
+ , HasWorldList a)
+ => LintConfig a -> LintConfig a
+expandWorlds config = config { configUriSchemas = configUriSchemas' }
+ where
+ configUriSchemas' =
+ M.insert "world:" [assemblysubsts] (configUriSchemas config)
+ assemblysubsts =
+ DomainSubstitution (M.fromList generated) ["map"]
+ where generated = configAssemblies config
+ <&> \slug -> (slug, "/@/"<>configEventSlug config<>"/"<>slug)
instance (FromJSON (LintConfig a)) => Argument (LintConfig a) where
parseArgument str =
diff --git a/lib/Properties.hs b/lib/Properties.hs
index 63cea1f..b937534 100644
--- a/lib/Properties.hs
+++ b/lib/Properties.hs
@@ -15,7 +15,7 @@ module Properties (checkMap, checkTileset, checkLayer) where
import Universum hiding (intercalate, isPrefixOf)
-import Data.Text (intercalate, isInfixOf, isPrefixOf)
+import Data.Text (intercalate, isPrefixOf)
import qualified Data.Text as T
import Data.Tiled (Layer (..), Object (..), Property (..),
PropertyValue (..), Tile (..),
@@ -42,8 +42,7 @@ import LintWriter (LintWriter, adjust, askContext,
import Paths (PathResult (..), RelPath (..),
getExtension, isOldStyle, parsePath)
import Types (Dep (Link, Local, LocalMap, MapLink))
-import Uris (SubstError (..), applySubsts,
- extractDomain, parseUri)
+import Uris (SubstError (..), applySubsts)
@@ -140,12 +139,9 @@ checkMapProperty p@(Property name _) = case name of
-- "canonical" form, but allowing that here so that multiple
-- scripts can be used by one map
_ | T.toLower name == "script" ->
- unwrapString p $ \str ->
- unless (checkIsRc3Url str &&
- not ( "/../" `isInfixOf` str) &&
- not ( "%" `isInfixOf` str) &&
- not ( "@" `isInfixOf` str))
- $ forbid "only scripts hosted on static.rc3.world are allowed."
+ unwrapURI (Proxy @"script") p
+ (dependsOn . Link)
+ (const $ forbid "scripts loaded from local files are disallowed")
| name `elem` ["jitsiRoom", "playAudio", "openWebsite"
, "url", "exitUrl", "silent", "getBadge"]
-> complain $ "property " <> name
@@ -342,11 +338,6 @@ checkObjectGroupProperty (Property name _) = case name of
\not the object layer."
_ -> warn $ "unknown property " <> prettyprint name <> " for objectgroup layers"
-checkIsRc3Url :: Text -> Bool
-checkIsRc3Url text= case extractDomain text of
- Nothing -> False
- Just domain -> do
- domain == "https://static.rc3.world"
-- | Checks a single (custom) property of a "normal" tile layer
@@ -405,7 +396,8 @@ checkTileThing removeExits p@(Property name _value) = case name of
unwrapURI (Proxy @"map") p
(\link -> do
assemblyslug <- lintConfig configAssemblyTag
- case T.stripPrefix ("/@/rc3_21/"<>assemblyslug<>"/") link of
+ eventslug <- lintConfig configEventSlug
+ case T.stripPrefix ("/@/"<>eventslug<>"/"<>assemblyslug<>"/") link of
Nothing -> do
dependsOn (MapLink link)
setProperty "exitUrl" link
@@ -424,8 +416,8 @@ checkTileThing removeExits p@(Property name _value) = case name of
let ext = getExtension path in
if | isOldStyle path ->
complain "Old-Style inter-repository links (using {<placeholder>}) \
- \cannot be used at rC3 2021; please use world:// instead \
- \(see howto.rc3.world)."
+ \cannot be used at divoc bb3; please use world:// instead \
+ \(see https://di.c3voc.de/howto:world)."
| ext == "tmx" ->
complain "Cannot use .tmx map format; use Tiled's json export instead."
| ext /= "json" ->
@@ -471,22 +463,21 @@ checkTileThing removeExits p@(Property name _value) = case name of
, "jitsiroomadmintag", "jitsiinterfaceconfig"
, "openwebsitepolicy", "allowapi" ]
-> forbidProperty name
- -- the openWebsite Api can only be allowed if the website is on static.rc3.world
- | T.toLower name == "openwebsiteallowapi"
- -> do
- properties <- askContext <&> getProperties
- unless (all (\(Property name value) -> case value of
- StrProp str -> name /= "openWebsite" || checkIsRc3Url str
- _ -> True
- ) properties)
- $ complain "\"openWebsiteAllowApi\" can only be used with websites hosted \
- \on https://static.rc3.world"
| name `elem` [ "openWebsite", "openTab" ] -> do
uselessEmptyLayer
- suggestProperty $ Property "openWebsiteTrigger" (StrProp "onaction")
- unwrapURI (Proxy @"website") p
- (dependsOn . Link)
- (const $ forbid "accessing local html files is disallowed.")
+ suggestProperty $ Property "openWebsiteTrigger" "onaction"
+
+ properties <- askContext <&> getProperties
+ let isScript = any (\(Property name _) ->
+ T.toLower name == "openwebsiteallowapi")
+ properties
+ if isScript
+ then unwrapURI (Proxy @"script") p
+ (dependsOn . Link)
+ (const $ forbid "accessing local html files is disallowed")
+ else unwrapURI (Proxy @"website") p
+ (dependsOn . Link)
+ (const $ forbid "accessing local html files is disallowed.")
| otherwise ->
when (not removeExits || name `notElem` [ "collides", "name", "tilesetCopyright" ]) $ do
warnUnknown p knownTileLayerProperites
@@ -634,11 +625,6 @@ setProperty name value = adjust $ \ctxt ->
$ \ps -> Just $ Property name (asProperty value) : filter sameName ps
where sameName (Property name' _) = name /= name'
-removeProperty :: HasProperties ctxt => Text -> LintWriter ctxt
-removeProperty name = adjust $ \ctxt ->
- flip adjustProperties ctxt
- $ \ps -> Just $ filter (\(Property name' _) -> name' /= name) ps
-
naiveEscapeProperty :: HasProperties a => Property -> LintWriter a
naiveEscapeProperty prop@(Property name _) =
unwrapString prop (setProperty name . naiveEscapeHTML)
@@ -691,7 +677,9 @@ unwrapBadgeToken str f = case parseToken str of
Nothing -> complain "invalid badge token."
--- | unwraps a URI
+-- | unwraps a link, giving two cases:
+-- - the link might be an (allowed) remote URI
+-- - the link might be relative to this map (i.e. just a filepath)
unwrapURI :: (KnownSymbol s, HasProperties a)
=> Proxy s
-> Property
@@ -715,12 +703,12 @@ unwrapURI sym p@(Property name _) f g = unwrapString p $ \link -> do
DomainDoesNotExist domain -> "The domain " <> domain <> " does not exist; \
\please make sure it is spelled correctly."
SchemaDoesNotExist schema ->
- "the URI schema " <> schema <> ":// cannot be used."
+ "the URI schema " <> schema <> "// cannot be used."
WrongScope schema allowed ->
- "the URI schema " <> schema <> ":// cannot be used in property \
+ "the URI schema " <> schema <> "// cannot be used in property \
\\"" <> name <> "\"; allowed "
<> (if length allowed == 1 then "is " else "are ")
- <> intercalate ", " (fmap (<> "://") allowed) <> "."
+ <> intercalate ", " (map (<> "//") allowed) <> "."
VarsDisallowed -> "extended API links are disallowed in links"
diff --git a/lib/Uris.hs b/lib/Uris.hs
index 596c272..40ea43e 100644
--- a/lib/Uris.hs
+++ b/lib/Uris.hs
@@ -1,9 +1,10 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE DeriveAnyClass #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TypeApplications #-}
-- | Functions to deal with uris and custom uri schemes
module Uris where
@@ -16,7 +17,8 @@ import Data.Aeson (FromJSON (..), Options (..),
import qualified Data.Map.Strict as M
import qualified Data.Text as T
import GHC.TypeLits (KnownSymbol, symbolVal)
-import Network.URI (URI (..), URIAuth (..), parseURI)
+import Network.URI (URI (..), URIAuth (..), parseURI,
+ uriToString)
import qualified Network.URI.Encode as URI
data Substitution =
@@ -24,7 +26,7 @@ data Substitution =
| DomainSubstitution { substs :: Map Text Text, scope :: [String] }
| Allowed { scope :: [String], allowed :: [Text] }
| Unrestricted { scope :: [String] }
- deriving (Generic, Show)
+ deriving (Generic, Show, NFData)
instance FromJSON Substitution where
@@ -33,30 +35,23 @@ instance FromJSON Substitution where
, rejectUnknownFields = True
}
-type SchemaSet = Map Text Substitution
+type SchemaSet = Map Text [Substitution]
-extractDomain :: Text -> Maybe Text
-extractDomain url =
- case parseUri url of
- Nothing -> Nothing
- Just (_,domain,_) -> Just domain
-
-
-
-
-parseUri :: Text -> Maybe (Text, Text, Text)
-parseUri uri =
- case parseURI (toString uri) of
+-- | deconstruct a URI into a triple of [schema:]//[domain]/[tail...],
+-- and a normalised version of the same URI
+parseUri :: Text -> Maybe (Text, Text, Text, Text)
+parseUri raw =
+ case parseURI (toString raw) of
Nothing -> Nothing
- Just parsedUri -> case uriAuthority parsedUri of
+ Just uri@URI{..} -> case uriAuthority of
Nothing -> Nothing
- -- https:
- Just uriAuth -> Just (T.replace (fromString ":") (fromString "") (fromString (uriScheme parsedUri )),
- -- //anonymous@ www.haskell.org :42
- fromString(uriUserInfo uriAuth++uriRegName uriAuth ++ uriPort uriAuth),
- -- /ghc ?query #frag
- fromString(uriPath parsedUri ++ uriQuery parsedUri ++ uriFragment parsedUri))
+ Just URIAuth {..} -> Just
+ ( fromString uriScheme
+ , fromString $ uriUserInfo <> uriRegName <> uriPort
+ , fromString $ uriPath <> uriQuery <> uriFragment
+ , fromString $ uriToString id uri ""
+ )
data SubstError =
@@ -66,41 +61,46 @@ data SubstError =
| IsBlocked
| DomainIsBlocked [Text]
| VarsDisallowed
+ | WrongScope Text [Text]
-- ^ This link's schema exists, but cannot be used in this scope.
-- The second field contains a list of schemas that may be used instead.
- | WrongScope Text [Text]
deriving (Eq, Ord) -- errors are ordered so we can show more specific ones
applySubsts :: KnownSymbol s
=> Proxy s -> SchemaSet -> Text -> Either SubstError Text
applySubsts s substs uri = do
- when (T.isInfixOf (toText "{{") uri || T.isInfixOf (toText "}}") uri)
+ when (T.isInfixOf "{{" uri || T.isInfixOf "}}" uri)
$ Left VarsDisallowed
- parts@(schema, _, _) <- note NotALink $ parseUri uri
+ parts@(schema, _, _, _) <- maybeToRight NotALink $ parseUri uri
- let rule = M.lookup schema substs
+ let rules = filter (elem thisScope . scope) . concat $ M.lookup schema substs
- case map (applySubst parts) rule of
- Nothing -> Left (SchemaDoesNotExist schema)
- Just result -> result
+ case nonEmpty $ map (applySubst parts) rules of
+ Nothing -> Left (SchemaDoesNotExist schema)
+ Just result -> minimum result
where
- note = maybeToRight
- applySubst (schema, domain, rest) rule = do
+ thisScope = symbolVal s
+ applySubst (schema, domain, rest, uri) rule = do
+
+ -- is this scope applicable?
unless (symbolVal s `elem` scope rule)
$ Left (WrongScope schema
- (map fst . filter (elem (symbolVal s) . scope . snd) $ toPairs substs))
+ $ map fst -- make list of available uri schemes
+ . filter (any (elem thisScope . scope) . snd)
+ $ toPairs substs)
+
case rule of
DomainSubstitution table _ -> do
- prefix <- note (DomainDoesNotExist (schema <> toText "://" <> domain))
- $ M.lookup domain table
+ prefix <- case M.lookup domain table of
+ Nothing -> Left (DomainDoesNotExist (schema <> "//" <> domain))
+ Just a -> Right a
pure (prefix <> rest)
Prefixed {..}
| domain `elem` blocked -> Left IsBlocked
- | domain `elem` allowed || toText "streamproxy.rc3.world" `T.isSuffixOf` domain -> Right uri
+ | domain `elem` allowed -> Right uri
| otherwise -> Right (prefix <> URI.encodeText uri)
- Allowed _ domains -> if domain `elem` domains
- || toText "streamproxy.rc3.world" `T.isSuffixOf` domain
- then Right uri
- else Left (DomainIsBlocked domains)
+ Allowed _ allowlist
+ | domain `elem` allowlist -> Right uri
+ | otherwise -> Left (DomainIsBlocked allowlist)
Unrestricted _ -> Right uri
diff --git a/server/Server.hs b/server/Server.hs
index 779509d..da2e73d 100644
--- a/server/Server.hs
+++ b/server/Server.hs
@@ -47,7 +47,8 @@ import Data.Either.Extra (mapLeft)
import Data.Functor.Contravariant (contramap)
import qualified Data.Map.Strict as M
import Lens.Micro.Platform (at, ix, makeLenses, traverseOf)
-import LintConfig (LintConfig')
+import LintConfig (ConfigKind (..), LintConfig,
+ feedConfig)
import Servant (FromHttpApiData)
import Servant.Client (BaseUrl, parseBaseUrl)
import qualified Text.Show as TS
@@ -89,7 +90,7 @@ toSha ref = Sha1
data Org (loaded :: Bool) = Org
{ orgSlug :: Text
- , orgLintconfig :: ConfigRes loaded LintConfig'
+ , orgLintconfig :: ConfigRes loaded (LintConfig Skeleton)
, orgEntrypoint :: FilePath
, orgGeneration :: Int
, orgRepos :: [RemoteRef]
@@ -97,7 +98,8 @@ data Org (loaded :: Bool) = Org
, orgWebdir :: Text
} deriving (Generic)
-instance NFData LintConfig' => NFData (Org True)
+instance NFData (LintConfig Skeleton) => NFData (Org True)
+deriving instance Show (LintConfig Skeleton) => Show (Org True)
-- | Orgs are compared via their slugs only
-- TODO: the server should probably refuse to start if two orgs have the
@@ -176,11 +178,15 @@ loadConfig path = do
Left err -> error $ prettyTomlDecodeErrors err
where
loadOrg :: Org False -> IO (Org True)
- loadOrg org = do
- lintconfig <- eitherDecodeFileStrict' (orgLintconfig org) >>= \case
- Right c -> pure c
- Left err -> error $ show err
- pure $ org { orgLintconfig = lintconfig }
+ loadOrg org@Org{..} = do
+ lintconfig <-
+ eitherDecodeFileStrict' orgLintconfig >>= \case
+ Right (c :: LintConfig Basic) -> pure c
+ Left err -> error $ show err
+ let config = org { orgLintconfig =
+ feedConfig lintconfig (map reponame orgRepos) orgSlug }
+ print config
+ pure config
data RealtimeMsg = RelintPending | Reload
deriving (Generic, ToJSON)
diff --git a/server/Worker.hs b/server/Worker.hs
index 8b3903c..a5fab58 100644
--- a/server/Worker.hs
+++ b/server/Worker.hs
@@ -22,12 +22,12 @@ import qualified Data.Text as T
import qualified Data.UUID as UUID
import qualified Data.UUID.V4 as UUID
import Fmt ((+|), (|+))
+import LintConfig (stuffConfig)
import Server (Config, JobStatus (..),
Org (..),
RealtimeMsg (RelintPending, Reload),
- RemoteRef (reporef, repourl),
- ServerState, adjustedPath,
- getJobStatus,
+ RemoteRef (..), ServerState,
+ adjustedPath, getJobStatus,
newRealtimeChannel,
setJobStatus, tmpdir, toSha)
import System.Directory (doesDirectoryExist)
@@ -63,6 +63,7 @@ runJob config Job {..} done = do
handle whoops
$ finally (lint workdir) (cleanup workdir)
where
+ lintConfig = stuffConfig (orgLintconfig jobOrg) (reponame jobRef)
lint workdir = do
maybeRealtime <- getJobStatus done (orgSlug jobOrg) (toSha jobRef) >>= \case
Nothing -> pure Nothing
@@ -80,9 +81,9 @@ runJob config Job {..} done = do
-- TODO: these calls fail for dumb http, add some fallback!
(callgit gitdir
[ "fetch", "origin", toString ref, "--depth", "1" ])
- (callgit gitdir
- [ "clone", toString ref, "--bare"
- , "--depth", "1", "-b", toString ref])
+ (callProcess "git"
+ [ "clone", toString url, "--bare"
+ , "--depth", "1", "-b", toString ref, gitdir])
rev <- map T.strip -- git returns a newline here
$ readgit' gitdir ["rev-parse", toString ref]
@@ -90,10 +91,10 @@ runJob config Job {..} done = do
callgit gitdir [ "worktree", "add", "--force", workdir, toString ref ]
- res <- recursiveCheckDir (orgLintconfig jobOrg) workdir (orgEntrypoint jobOrg)
+ res <- recursiveCheckDir lintConfig workdir (orgEntrypoint jobOrg)
>>= evaluateNF
- writeAdjustedRepository (orgLintconfig jobOrg) workdir (toString outPath) res
+ writeAdjustedRepository lintConfig workdir (toString outPath) res
>>= runStdoutLoggingT . \case
ExitSuccess ->
logInfoN $ "linted map "+| (show jobRef :: Text) |+"."
@@ -126,7 +127,6 @@ runJob config Job {..} done = do
url = repourl jobRef
ref = reporef jobRef
- callgit = callgit'
gitdir = view tmpdir config </> toString hashedname
hashedname = T.map escapeSlash url
where escapeSlash = \case { '/' -> '-'; a -> a }
@@ -137,8 +137,8 @@ readgit' dir args = map toText $
print args
readProcess "git" ([ "-C", toString dir ] <> args) ""
-callgit' :: MonadIO m => FilePath -> [String] -> m ()
-callgit' dir args =
+callgit :: MonadIO m => FilePath -> [String] -> m ()
+callgit dir args =
liftIO $ do
print args
callProcess "git" ([ "-C", toString dir ] <> args)
diff --git a/src/Main.hs b/src/Main.hs
index b2002bf..9628e1e 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}
@@ -15,9 +16,9 @@ import Data.Aeson.Encode.Pretty (encodePretty)
import Data.Aeson.KeyMap (coercionToHashMap)
import WithCli (HasArguments, withCli)
-import CheckDir (recursiveCheckDir, resultIsFatal, DirResult (dirresultGraph))
-import Control.Monad (when)
-import LintConfig (LintConfig (..), patchConfig)
+import CheckDir (recursiveCheckDir, resultIsFatal)
+import LintConfig (ConfigKind (..), LintConfig (..),
+ patchConfig)
import System.Exit (ExitCode (ExitFailure))
import Types (Level (..))
import Util (printPretty)
@@ -40,7 +41,7 @@ data Options = Options
-- ^ path to write the (possibly adjusted) maps to after linting
, configFile :: Maybe FilePath
-- ^ path to a config file. Currently required.
- , config :: Maybe (LintConfig Maybe)
+ , config :: Maybe (LintConfig Patch)
-- ^ a "patch" for the configuration file
, version :: Bool
, dot :: Bool
diff --git a/src/Version.hs b/src/Version.hs
index 2ec1537..e62c9b8 100644
--- a/src/Version.hs
+++ b/src/Version.hs
@@ -9,7 +9,7 @@ import qualified Language.Haskell.TH as TH
import System.Process (readProcess)
version :: String
-version = "walint rc3 2021 (" <>
+version = "walint divoc bb3 2022 (" <>
$(do
hash <- liftIO $ catchAny (readProcess "git" ["rev-parse", "HEAD"] "")
(\_ -> pure "[unknown]")