summaryrefslogtreecommitdiff
path: root/lib/Properties.hs
blob: ebd34bb9a9262b1eb56d503586f0209f9323b386 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
{-# LANGUAGE NamedFieldPuns    #-}
{-# LANGUAGE OverloadedStrings #-}

-- | Contains checks for custom properties of the map json
module Properties (checkProperty) where


import           Control.Monad (unless)
import           Data.Text     (Text, isPrefixOf)
import           Tiled2        (Layer (layerProperties), Property, propertyName,
                                propertyValue)
import           Util          (prettyprint)

import           LintWriter    (LintWriter, complain, dependsOn, forbid, info,
                                suggest, warn)
import           Types
-- | the point of this module
--
-- given a property, check if it is valid. It gets a reference
-- to its own layer since sometimes the presense of one property
-- implies the presence or absense of another.
--
-- The tests in here are meant to comply with the informal spec
-- at https://workadventu.re/map-building
--
-- I've attempted to build the LintWriter monad in a way
-- that should make this readable even to non-Haskellers
-- TODO: also pass the value of this property directly
checkProperty :: Layer -> Property -> LintWriter ()
checkProperty layer prop = case propName of
    "jitsiRoom" -> do
      info $ "found jitsi room: " <> prettyprint (propertyValue prop)
      suggestPropertyValue "jitsiTrigger" "onaction"
    "jitsiTrigger" ->
      requireProperty "jitsiRoom"
    "jitsiUrl" -> isForbidden
    "jitsiConfig" -> isForbidden
    "jitsiClientConfig" -> isForbidden
    "jitsiRoomAdminTag" -> isForbidden
    "playAudio" ->
      forbidHTTPAndThen $ dependsOn $ if "https://" `isPrefixOf` propValue
        then Link propValue
        else Local propValue
    "audioLoop" ->
      requireProperty "playAudio"
    "audioVolume" ->
      requireProperty "playAudio"
    "openWebsite" -> do
      suggestPropertyValue "openWebsiteTrigger" "onaction"
      if "http://" `isPrefixOf` propValue
        then complain "cannot load content over http into map, please use https or include your assets locally"
        else dependsOn $
          if "https://" `isPrefixOf` propValue
          then Link propValue
          else Local propValue
    "openWebsiteTrigger" ->
      requireProperty "openWebsite"
    "openWebsitePolicy" ->
      requireProperty "openWebsite"
    "exitUrl" ->
      forbidHTTPAndThen $ dependsOn $ if "https://" `isPrefixOf` propValue
        then MapLink propValue
        else LocalMap propValue
    "startLayer" -> pure ()
      -- could also make this a "hard error" (i.e. Left), but then it
      -- stops checking other properties as checkLayer short-circuits.
    _ -> warn $ "unknown property type " <> prettyprint propName
    where
      propName = propertyName prop
      propValue = propertyValue prop
      -- | require some property in this layer
      requireProperty name = unless (hasProperty name layer)
        $ complain $ "property "<>prettyprint name<>" requires property "<>prettyprint propName
      -- | This property is forbidden and should not be used
      isForbidden = forbid $ "property " <> prettyprint propName <> " should not be used"
      -- TODO: check if the property has the correct value
      suggestPropertyValue :: Text -> Text -> LintWriter ()
      suggestPropertyValue name value = unless (hasProperty name layer)
        $ suggest $ "set property " <> prettyprint name <> " to " <> prettyprint value
      forbidHTTPAndThen :: LintWriter () -> LintWriter ()
      forbidHTTPAndThen andthen = if "http://" `isPrefixOf` propValue
        then complain "cannot access content via http; either use https or include it locally instead."
        else andthen




-- | does this layer have the given property?
hasProperty :: Text -> Layer -> Bool
hasProperty name = any
  (\prop -> propertyName prop == name)
  . layerProperties