Merge branch 'master' of gitlab.cip.ifi.lmu.de:jost/UniWorX

This commit is contained in:
SJost 2017-11-24 15:20:31 +01:00
commit 10608b6256
8 changed files with 104 additions and 66 deletions

View File

@ -1,13 +1,6 @@
# After you've edited this file, remove the following line to allow root: ..
# `yesod keter` to build your bundle.
user-edited: false
# A Keter app is composed of 1 or more stanzas. The main stanza will define our
# web application. See the Keter documentation for more information on
# available stanzas.
stanzas: stanzas:
# Your Yesod application.
- type: webapp - type: webapp
# Name of your executable. You are unlikely to need to change this. # Name of your executable. You are unlikely to need to change this.
@ -22,49 +15,28 @@ stanzas:
args: [] args: []
hosts: hosts:
# You can specify one or more hostnames for your application to respond - testworx.tcs.ifi.lmu.de
# to. The primary hostname will be used for generating your application
# root.
- www.uniworx.com
# Enable to force Keter to redirect to https ssl: true
# Can be added to any stanza
requires-secure: false
# Static files. forward-env:
- type: static-files - LDAPURI
hosts: - LDAPDN
- static.uniworx.com - LDAPPW
root: ../static - LDAPBN
- DUMMY_LOGIN
# Uncomment to turn on directory listings. - DETAILED_LOGGING
# directory-listing: true - LOG_ALL
# Redirect plain domain name to www.
- type: redirect
hosts:
- uniworx.com
actions:
- host: www.uniworx.com
# secure: false
# port: 80
# Uncomment to switch to a non-permanent redirect.
# status: 303
# Use the following to automatically copy your bundle upon creation via `yesod # Use the following to automatically copy your bundle upon creation via `yesod
# keter`. Uses `scp` internally, so you can set it to a remote destination # keter`. Uses `scp` internally, so you can set it to a remote destination
# copy-to: user@host:/opt/keter/incoming/ # copy-to: user@host:/opt/keter/incoming/
copy-to: keter@testworx.tcs.ifi.lmu.de:/opt/keter/incoming/
# You can pass arguments to `scp` used above. This example limits bandwidth to copy-to-args:
# 1024 Kbit/s and uses port 2222 instead of the default 22 - "-P 30363"
# copy-to-args:
# - "-l 1024"
# - "-P 2222"
# If you would like to have Keter automatically create a PostgreSQL database # If you would like to have Keter automatically create a PostgreSQL database
# and set appropriate environment variables for it to be discovered, uncomment # and set appropriate environment variables for it to be discovered, uncomment
# the following line. # the following line.
# plugins: plugins:
# postgres: true postgres: true

View File

@ -8,17 +8,17 @@ ip-from-header: "_env:IP_FROM_HEADER:false"
# Default behavior: determine the application root from the request headers. # Default behavior: determine the application root from the request headers.
# Uncomment to set an explicit approot # Uncomment to set an explicit approot
#approot: "_env:APPROOT:http://localhost:3000" approot: "_env:APPROOT:http://localhost:3000"
# Optional values with the following production defaults. # Optional values with the following production defaults.
# In development, they default to the inverse. # In development, they default to the inverse.
# #
# detailed-logging: false detailed-logging: "_env:DETAILED_LOGGING:false"
# should-log-all: false should-log-all: "_env:LOG_ALL:false"
# reload-templates: false # reload-templates: false
# mutable-static: false # mutable-static: false
# skip-combining: false # skip-combining: false
# auth-dummy-login : false auth-dummy-login: "_env:DUMMY_LOGIN:false"
# NB: If you need a numeric value (e.g. 123) to parse as a String, wrap it in single quotes (e.g. "_env:PGPASS:'123'") # NB: If you need a numeric value (e.g. 123) to parse as a String, wrap it in single quotes (e.g. "_env:PGPASS:'123'")
# See https://github.com/yesodweb/yesod/wiki/Configuration#parsing-numeric-values-as-strings # See https://github.com/yesodweb/yesod/wiki/Configuration#parsing-numeric-values-as-strings
@ -32,6 +32,12 @@ database:
database: "_env:PGDATABASE:uniworx" database: "_env:PGDATABASE:uniworx"
poolsize: "_env:PGPOOLSIZE:10" poolsize: "_env:PGPOOLSIZE:10"
ldap:
uri: "_env:LDAPURI:ldap://localhost:389"
dn: "_env:LDAPDN:uniworx"
password: "_env:LDAPPW:"
basename: "_env:LDAPBN:"
cryptoid-keyfile: "_env:CRYPTOID_KEYFILE:cryptoid_key.bf" cryptoid-keyfile: "_env:CRYPTOID_KEYFILE:cryptoid_key.bf"
copyright: Insert copyright statement here copyright: Insert copyright statement here

6
docker/Dockerfile Normal file
View File

@ -0,0 +1,6 @@
FROM fpco/stack-build:lts-9.3
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update
RUN apt-get install libldap2-dev libsasl2-dev

2
models
View File

@ -1,7 +1,7 @@
User User
plugin Text plugin Text
ident Text ident Text
matrikelnummer Text matrikelnummer Text Maybe
UniqueAuthentication plugin ident UniqueAuthentication plugin ident
Term json Term json
name TermIdentifier name TermIdentifier

View File

@ -72,6 +72,8 @@ dependencies:
- generic-deriving - generic-deriving
- blaze-html - blaze-html
- conduit-resumablesink >=0.2 - conduit-resumablesink >=0.2
- yesod-auth-ldap
- LDAP
# The library contains all of our application code. The executable # The library contains all of our application code. The executable
# defined below is just a thin wrapper. # defined below is just a thin wrapper.

View File

@ -6,6 +6,7 @@
{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE PatternGuards #-} {-# LANGUAGE PatternGuards #-}
module Foundation where module Foundation where
@ -16,9 +17,13 @@ import Text.Hamlet (hamletFile)
import Text.Jasmine (minifym) import Text.Jasmine (minifym)
-- Used only when in "auth-dummy-login" setting is enabled. -- Used only when in "auth-dummy-login" setting is enabled.
import Yesod.Auth.Message
import Yesod.Auth.Dummy import Yesod.Auth.Dummy
import Yesod.Auth.LDAP
import LDAP.Data (LDAPScope(..))
import LDAP.Search (LDAPEntry(..))
import Yesod.Auth.OpenId (authOpenId, IdentifierType (Claimed))
import Yesod.Default.Util (addStaticContentExternal) import Yesod.Default.Util (addStaticContentExternal)
import Yesod.Core.Types (Logger) import Yesod.Core.Types (Logger)
import qualified Yesod.Core.Unsafe as Unsafe import qualified Yesod.Core.Unsafe as Unsafe
@ -279,29 +284,54 @@ instance YesodAuth UniWorX where
-- Override the above two destinations when a Referer: header is present -- Override the above two destinations when a Referer: header is present
redirectToReferer _ = True redirectToReferer _ = True
authenticate Creds{..} = runDB $ do authenticate creds@(Creds{..}) = runDB $ do
let (plugin, ident) let (userPlugin, userIdent)
| credsPlugin == "dummy" | isDummy
, [dummyPlugin, dummyIdent] <- Text.splitOn ":" credsIdent , [dummyPlugin, dummyIdent] <- Text.splitOn ":" credsIdent
= (dummyPlugin, dummyIdent) = (dummyPlugin, dummyIdent)
| otherwise | otherwise
= (credsPlugin, credsIdent) = (credsPlugin, credsIdent)
x <- getBy $ UniqueAuthentication plugin ident isDummy = credsPlugin == "dummy"
case x of uAuth = UniqueAuthentication userPlugin userIdent
Just (Entity uid _) -> return $ Authenticated uid
Nothing -> Authenticated <$> insert User $logDebugS "auth" $ tshow ((userPlugin, userIdent), creds)
{ userPlugin = plugin
, userIdent = ident case isDummy of
, userMatrikelnummer = "DummyMatrikel" True ->
} maybe (UserError $ IdentifierNotFound credsIdent) (Authenticated . entityKey) <$> getBy uAuth
False -> do
let
userMatrikelnummer = lookup "LMU-Stud-Matrikelnummer" credsExtra
newUser = User{..}
userUpdate = [ UserMatrikelnummer =. userMatrikelnummer
]
Authenticated . entityKey <$> upsertBy uAuth newUser userUpdate
-- You can add other plugins like Google Email, email or OAuth here -- You can add other plugins like Google Email, email or OAuth here
authPlugins app = [authOpenId Claimed []] ++ extraAuthPlugins authPlugins app = [genericAuthLDAP $ ldapConfig app] ++ extraAuthPlugins
-- Enable authDummy login if enabled. -- Enable authDummy login if enabled.
where extraAuthPlugins = [authDummy | appAuthDummyLogin $ appSettings app] where extraAuthPlugins = [authDummy | appAuthDummyLogin $ appSettings app]
authHttpManager = getHttpManager authHttpManager = getHttpManager
ldapConfig :: UniWorX -> LDAPConfig
ldapConfig app@(appSettings -> settings) = LDAPConfig
{ usernameFilter = \u -> principalName <> "=" <> u
, identifierModifier
, ldapUri = appLDAPURI settings
, initDN = appLDAPDN settings
, initPass = appLDAPPw settings
, baseDN = appLDAPBaseName settings
, ldapScope = LdapScopeSubtree
}
where
principalName :: IsString a => a
principalName = "userPrincipalName"
identifierModifier _ entry = case lookup principalName $ leattrs entry of
Just [n] -> Text.pack n
_ -> error "Could not determine user principal name"
-- | Access function to determine if a user is logged in. -- | Access function to determine if a user is logged in.
isAuthenticated :: Handler AuthResult isAuthenticated :: Handler AuthResult
isAuthenticated = do isAuthenticated = do

View File

@ -43,6 +43,11 @@ data AppSettings = AppSettings
-- ^ Get the IP address from the header when logging. Useful when sitting -- ^ Get the IP address from the header when logging. Useful when sitting
-- behind a reverse proxy. -- behind a reverse proxy.
, appLDAPURI :: String
, appLDAPDN :: String
, appLDAPPw :: String
, appLDAPBaseName :: Maybe String
, appDetailedRequestLogging :: Bool , appDetailedRequestLogging :: Bool
-- ^ Use detailed request logging system -- ^ Use detailed request logging system
, appShouldLogAll :: Bool , appShouldLogAll :: Bool
@ -80,6 +85,9 @@ instance FromJSON AppSettings where
appPort <- o .: "port" appPort <- o .: "port"
appIpFromHeader <- o .: "ip-from-header" appIpFromHeader <- o .: "ip-from-header"
( appLDAPURI, appLDAPDN, appLDAPPw, appLDAPBaseName )
<- (=<< o .: "ldap") . withObject "LDAP" $ \obj -> (,,,) <$> obj .: "uri" <*> obj .: "dn" <*> obj .: "password" <*> obj .:? "basename"
appDetailedRequestLogging <- o .:? "detailed-logging" .!= defaultDev appDetailedRequestLogging <- o .:? "detailed-logging" .!= defaultDev
appShouldLogAll <- o .:? "should-log-all" .!= defaultDev appShouldLogAll <- o .:? "should-log-all" .!= defaultDev
appReloadTemplates <- o .:? "reload-templates" .!= defaultDev appReloadTemplates <- o .:? "reload-templates" .!= defaultDev

View File

@ -1,5 +1,9 @@
flags: {} flags: {}
docker:
enable: true
image: uniworx
nix: nix:
enable: false
packages: [] packages: []
pure: false pure: false
shell-file: ./stack.nix shell-file: ./stack.nix
@ -10,6 +14,14 @@ packages:
git: https://github.com/pngwjpgh/zip-stream.git git: https://github.com/pngwjpgh/zip-stream.git
commit: 9272bbed000928d500febad1cdc98d1da29d399e commit: 9272bbed000928d500febad1cdc98d1da29d399e
extra-dep: true extra-dep: true
- location:
git: https://github.com/mlitchard/yesod-auth-ldap.git
commit: 69e08ef687ab96df3352ff4267562135453c6f02
extra-dep: true
- location:
git: https://github.com/mlitchard/authenticate-ldap.git
commit: cc2770024766a8fa29d3086688df60aaf65fb954
extra-dep: true
extra-deps: extra-deps:
- colonnade-1.1.1 - colonnade-1.1.1
- yesod-colonnade-1.1.0 - yesod-colonnade-1.1.0
@ -22,4 +34,6 @@ extra-deps:
- encoding-0.8.2 - encoding-0.8.2
- regex-compat-0.93.1 - regex-compat-0.93.1
- LDAP-0.6.11
resolver: lts-9.3 resolver: lts-9.3