diff options
| author | LLLL Colonq <llll@colonq> | 2024-11-07 22:51:56 -0500 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2024-11-07 22:51:56 -0500 |
| commit | 309bdcc15db562633ff73da4021f0020f1c0cf6d (patch) | |
| tree | e465b2035d0bed8c53960322ff041122299cbd2f | |
| parent | 624f7ba8b2fcda6675951dd8d41dcc99017484cf (diff) | |
Secured API
| -rw-r--r-- | fig-monitor-twitch/main/Main.hs | 10 | ||||
| -rw-r--r-- | fig-web/fig-web.cabal | 1 | ||||
| -rw-r--r-- | fig-web/main/Main.hs | 25 | ||||
| -rw-r--r-- | fig-web/src/Fig/Web/Secure.hs | 64 | ||||
| -rw-r--r-- | flake.nix | 47 | ||||
| -rw-r--r-- | hie.yaml | 8 |
6 files changed, 139 insertions, 16 deletions
diff --git a/fig-monitor-twitch/main/Main.hs b/fig-monitor-twitch/main/Main.hs index b306586..682d35b 100644 --- a/fig-monitor-twitch/main/Main.hs +++ b/fig-monitor-twitch/main/Main.hs @@ -11,7 +11,7 @@ data Command = Monitor | Chatbot | LiveChecker - | RedirectServer Bool + | RedirectServer !Bool | Validate parseCommand :: Parser Command @@ -24,10 +24,10 @@ parseCommand = subparser $ mconcat , command "validate-endpoint" $ info (pure Validate) (progDesc "Test Twitch authentication") ] data Opts = Opts - { busHost :: Text - , busPort :: Text - , config :: FilePath - , command :: Command + { busHost :: !Text + , busPort :: !Text + , config :: !FilePath + , command :: !Command } parseOpts :: Parser Opts diff --git a/fig-web/fig-web.cabal b/fig-web/fig-web.cabal index 3cf3502..600d4d8 100644 --- a/fig-web/fig-web.cabal +++ b/fig-web/fig-web.cabal @@ -55,6 +55,7 @@ library hs-source-dirs: src exposed-modules: Fig.Web + Fig.Web.Secure Fig.Web.Utils Fig.Web.Auth Fig.Web.State diff --git a/fig-web/main/Main.hs b/fig-web/main/Main.hs index 890c010..926685c 100644 --- a/fig-web/main/Main.hs +++ b/fig-web/main/Main.hs @@ -6,13 +6,25 @@ import Fig.Prelude import Options.Applicative -import Fig.Web import Fig.Web.Utils +import qualified Fig.Web as Public +import qualified Fig.Web.Secure as Secure + +data Command + = Public + | Secure + +parseCommand :: Parser Command +parseCommand = subparser $ mconcat + [ command "public" $ info (pure Public) (progDesc "Launch the public web server") + , command "secure" $ info (pure Secure) (progDesc "Launch the private web server (intended to be run behind authentication proxy)") + ] data Opts = Opts - { busHost :: Text - , busPort :: Text - , config :: FilePath + { busHost :: !Text + , busPort :: !Text + , config :: !FilePath + , command :: !Command } parseOpts :: Parser Opts @@ -20,6 +32,7 @@ parseOpts = do busHost <- strOption (long "bus-host" <> metavar "HOST" <> help "Address of message bus" <> value "localhost") busPort <- strOption (long "bus-port" <> metavar "PORT" <> help "Message bus port" <> showDefault <> value "32050") config <- strOption (long "config" <> metavar "PATH" <> help "Path to config file" <> showDefault <> value "fig-web.toml") + command <- parseCommand pure Opts{..} main :: IO () @@ -29,4 +42,6 @@ main = do <> header "fig-web - public-facing web applications" ) cfg <- loadConfig opts.config - server cfg (opts.busHost, opts.busPort) + case cfg.command of + Public -> Public.server cfg (opts.busHost, opts.busPort) + Secure -> Secure.server cfg (opts.busHost, opts.busPort) diff --git a/fig-web/src/Fig/Web/Secure.hs b/fig-web/src/Fig/Web/Secure.hs new file mode 100644 index 0000000..dfb7e1b --- /dev/null +++ b/fig-web/src/Fig/Web/Secure.hs @@ -0,0 +1,64 @@ +{-# Language QuasiQuotes #-} + +module Fig.Web where + +import Fig.Prelude + +import System.Random (randomRIO) + +import Control.Monad (unless) +import Control.Lens (use, (^?), Ixed (..)) +import qualified Control.Concurrent.Chan as Chan +import qualified Control.Concurrent.MVar as MVar + +import Data.Maybe (mapMaybe) +import qualified Data.Text as Text +import qualified Data.Text.Lazy as Text.L +import qualified Data.ByteString.Base64 as BS.Base64 +import qualified Data.Set as Set + +import qualified Network.Wai as Wai +-- import qualified Network.Wai.Middleware.Static as Wai.Static +import qualified Network.Wai.Handler.Warp as Warp +import qualified Network.WebSockets as WS + +import qualified Web.Scotty as Sc + +import Fig.Utils.SExpr +import Fig.Bus.Client +import Fig.Web.Utils +import Fig.Web.Auth +import Fig.Web.State +import qualified Fig.Web.DB as DB + +data LiveEvent + = LiveEventOnline !(Set.Set Text) + | LiveEventOffline !(Set.Set Text) + deriving (Show, Eq, Ord) + +server :: Config -> (Text, Text) -> IO () +server cfg busAddr = do + log $ "Web server running on port " <> tshow cfg.port + busClient busAddr + (\cmds -> do + log "Connected to bus!" + Warp.run cfg.port =<< app cfg cmds + ) + (\_cmds d -> do + log $ "Invalid event: " <> tshow d + ) + (pure ()) + +sexprStr :: Text -> SExpr +sexprStr = SExprString . BS.Base64.encodeBase64 . encodeUtf8 + +app :: Config -> Commands IO -> IO Wai.Application +app cfg cmds = do + log "Connecting to database..." + db <- DB.connect cfg + log "Connected! Secure server active." + Sc.scottyApp do + Sc.get "/" do + Sc.text "this is the secure endpoint" + Sc.notFound do + Sc.text "not found" @@ -273,7 +273,6 @@ description = "Path to config file"; default = pkgs.writeText "fig-web.toml" '' port = 8000 - asset_path = "./fig-web-assets" client_id = "" auth_token = "" db_host = "" @@ -285,7 +284,7 @@ wantedBy = ["multi-user.target"]; serviceConfig = { Restart = "on-failure"; - ExecStart = "${haskellPackages.fig-web}/bin/fig-web --bus-host ${cfg.busHost} --bus-port ${toString cfg.busPort} --config ${cfg.configFile}"; + ExecStart = "${haskellPackages.fig-web}/bin/fig-web public --bus-host ${cfg.busHost} --bus-port ${toString cfg.busPort} --config ${cfg.configFile}"; DynamicUser = "yes"; RuntimeDirectory = "colonq.fig-web"; RuntimeDirectoryMode = "0755"; @@ -297,6 +296,50 @@ }; }; }; + figWebSecureModule = { config, lib, ... }: + let + cfg = config.colonq.services.fig-web-secure; + in { + options.colonq.services.fig-web-secure = { + enable = lib.mkEnableOption "Enable the fig web server (secure)"; + busHost = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + description = "Message bus port"; + }; + busPort = lib.mkOption { + type = lib.types.port; + default = 32050; + description = "Address of message bus"; + }; + configFile = lib.mkOption { + type = lib.types.path; + description = "Path to config file"; + default = pkgs.writeText "fig-web-secure.toml" '' + port = 8000 + client_id = "" + auth_token = "" + db_host = "" + ''; + }; + }; + config = lib.mkIf cfg.enable { + systemd.services."colonq.fig-web-secure" = { + wantedBy = ["multi-user.target"]; + serviceConfig = { + Restart = "on-failure"; + ExecStart = "${haskellPackages.fig-web}/bin/fig-web secure --bus-host ${cfg.busHost} --bus-port ${toString cfg.busPort} --config ${cfg.configFile}"; + DynamicUser = "yes"; + RuntimeDirectory = "colonq.fig-web-secure"; + RuntimeDirectoryMode = "0755"; + StateDirectory = "colonq.fig-web-secure"; + StateDirectoryMode = "0700"; + CacheDirectory = "colonq.fig-web-secure"; + CacheDirectoryMode = "0750"; + }; + }; + }; + }; in { devShells.x86_64-linux.default = haskellPackages.shellFor { packages = hspkgs: with hspkgs; [ @@ -26,10 +26,10 @@ cradle: config: { cradle: { cabal: { component: "fig-bridge-irc-discord:lib:fig-bridge-irc-discord" } } } - path: "./fig-bridge-irc-discord/main/" config: { cradle: { cabal: { component: "fig-bridge-irc-discord:exe:fig-bridge-irc-discord" } } } - - path: "./fig-frontend/src/" - config: { cradle: { cabal: { component: "fig-frontend:lib:fig-frontend" } } } - - path: "./fig-frontend/main/" - config: { cradle: { cabal: { component: "fig-frontend:exe:fig-frontend" } } } + - path: "./fig-web/src/" + config: { cradle: { cabal: { component: "fig-web:lib:fig-web" } } } + - path: "./fig-web/main/" + config: { cradle: { cabal: { component: "fig-web:exe:fig-web" } } } - path: "./fig-bless/src/" config: { cradle: { cabal: { component: "fig-bless:lib:fig-bless" } } } - path: "./fig-bless/main/" |
