Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
student-projects
bamapro-2018-ss
Commits
36fcac79
Commit
36fcac79
authored
Sep 26, 2018
by
Dennis Pehlke
Browse files
Merged master into syntaxDiff
parents
11bf6004
445bc218
Changes
38
Expand all
Hide whitespace changes
Inline
Side-by-side
Masala/public/js/masala.js
View file @
36fcac79
...
...
@@ -3,6 +3,15 @@ function doSearch()
document
.
location
=
"
spicey.cgi?Search/search/
"
+
$
(
"
#searchfield
"
)[
0
].
value
;
}
// get value of cells for sorting
const
getCellValue
=
(
tr
,
idx
)
=>
tr
.
children
[
idx
].
innerText
||
tr
.
children
[
idx
].
textContent
;
// compare two cells, either numeric values or strings
const
comparer
=
(
idx
,
asc
)
=>
(
a
,
b
)
=>
((
v1
,
v2
)
=>
v1
!==
''
&&
v2
!==
''
&&
!
isNaN
(
v1
)
&&
!
isNaN
(
v2
)
?
v1
-
v2
:
v1
.
toString
().
localeCompare
(
v2
))
(
getCellValue
(
asc
?
a
:
b
,
idx
),
getCellValue
(
asc
?
b
:
a
,
idx
));
document
.
addEventListener
(
"
DOMContentLoaded
"
,
function
(
event
)
{
$
(
"
#searchfield
"
).
keydown
(
function
(
e
){
if
(
e
.
keyCode
==
13
)
{
...
...
@@ -15,5 +24,29 @@ document.addEventListener("DOMContentLoaded", function(event) {
$
(
"
#menu-toggle
"
).
click
(
function
(
e
){
e
.
preventDefault
();
$
(
"
#wrapper
"
).
toggleClass
(
"
menuDisplayed
"
);
});
});
$
(
'
th
'
).
click
(
function
(){
var
table
=
$
(
this
).
parents
(
'
table
'
).
eq
(
0
)
var
rows
=
table
.
find
(
'
tr:gt(0)
'
).
toArray
().
sort
(
comparer
(
$
(
this
).
index
()))
this
.
asc
=
!
this
.
asc
if
(
!
this
.
asc
){
rows
=
rows
.
reverse
()
}
for
(
var
i
=
0
;
i
<
rows
.
length
;
i
++
){
table
.
append
(
rows
[
i
])
}
$
(
'
.sort-asc
'
).
removeClass
(
'
sort-asc
'
)
$
(
'
.sort-desc
'
).
removeClass
(
'
sort-desc
'
)
$
(
this
).
addClass
(
this
.
asc
?
'
sort-asc
'
:
'
sort-desc
'
)
})
});
// add listener to sort any HTML tables by clicking the headers
/*document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
const table = th.closest('table');
Array.from(table.querySelectorAll('tr:not(:first-child)'))
.sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
.forEach(tr => table.appendChild(tr) );
}))); */
Masala/src/Config/Config_template.curry
0 → 100755
View file @
36fcac79
module Config.Config where
--- The name of the SQLite database file.
sqliteDBFile :: String
sqliteDBFile = "../Masala.db"
--- The complete root URL where the deployed system can be reached.
--- This can be used in various places, e.g. to provide full URLs in email notifications.
--- It must include the preferred protocol (http, https) and must not include a
--- trailing forward slash.
rootUrl :: String
rootUrl = "http://127.0.0.1/Masala"
--- This is the system-specific Key (a.k.a. "pepper") used in password hash generation,
--- in concatenation with the user Password and randomly generated Salt.
--- This key should be changed to a different random string of sufficient length
--- (12 characters is considered good) before the system is compiled for
--- deployment in production.
--- It must not be changed thereafter, for this would cause logins to previously created accounts to fail.
--- The key used in production should be kept secret. A leak or accidental disclosure will
--- nullify the additional account security it provides in the event of a database leak.
--- Specifically, an attacker then has the ability to efficiently run dictionary and brute-force
--- attacks against individual user account hashes, using the known Salt and systemkey.
--- In the event of a leak of this key or the database file, it is advised to :
--- (1) Temporarily disable logins to the system
--- (2) Identify and close the leak
--- (3) Implement a second, different systemkey that is used in all subsequent account
--- creations and password changes. User accounts should be tagged if they use the new key.
--- (4) Force all untagged users to change their password on the next login,
--- causing their password hash to be created from the new secret systemkey.
--- The old systemkey must still be stored to be able to verify the password of old accounts.
--- (5) Send an email to all users to inform them of the security breach, that their passwords might be
--- endangered, and that they should change their password immediately.
systemkey :: String
systemkey = "p9-2xK!81$W7"
-- The default mail profile. You can easily change this to reference one of those declared below.
mailProfDefault :: (String, ([String] -> [String]))
mailProfDefault = mailProfMailx
-- The sender email address to use for admin emails
adminEmail :: String
adminEmail = "noreply@informatik.uni-kiel.de"
-- Send mail with mailx ignoring the system configuration (send directly to recipient's mailserver)
-- This may work when inside the Uni Kiel network and sending mail to an IfI recipient.
-- Most mail providers will reject such mail from home IPs though, for spam protection.
mailProfRawMailx :: (String, ([String] -> [String]))
mailProfRawMailx = ("mailx", (\[subject, to] -> ["-n", "-a", "From: " ++ adminEmail, "-s", subject, to]))
-- Send mail with mailx using the system configuration
mailProfMailx :: (String, ([String] -> [String]))
mailProfMailx = ("mailx", (\[subject, to] -> ["-s", subject, to]))
-- Simply write mail content to local file 'mail.log' (for testing)
mailProfLogFile :: (String, ([String] -> [String]))
mailProfLogFile = ("sed", (\_ -> ["-n", "w mail.log"]))
-- Remote URL of the MasalaJob /api/job endpoint, use 'Nothing' if there is no remote server used
masalaJobServer :: Maybe String
masalaJobServer = Nothing
--------------------------------------------------------------------------
\ No newline at end of file
Masala/src/Config/RoutesData.curry
View file @
36fcac79
...
...
@@ -2,6 +2,7 @@ module Config.RoutesData where
import System.Authentication
import System.SessionInfo
import System.Authorization
data ControllerReference = ProcessListController
| LoginController
...
...
@@ -20,7 +21,7 @@ data UrlMatch = Exact String
| Matcher (String -> Bool)
| Always
type Route = (String,UrlMatch,ControllerReference, (
Bool
-> Bool))
type Route = (String,UrlMatch,ControllerReference, (
UserSessionInfo
-> Bool))
--- This constant specifies the association of URLs to controllers.
...
...
@@ -31,25 +32,23 @@ type Route = (String,UrlMatch,ControllerReference, (Bool -> Bool))
getRoutes :: IO [Route]
getRoutes =
do login <- getSessionLogin
r
et
urn $ maybe [] (\ld ->
[("Settings", Prefix "User" (ldName ld ++ "/settings"), UserController, id)]) logi
n
++
[
("Search", Prefix "Search" "search",SearchController, const False)
l
et
loginName = maybe "" ldName login
retur
n
[("Settings", Prefix "User" (loginName ++ "/settings"), UserController, isLoggedIn)
,
("Search", Prefix "Search" "search",SearchController, const False)
,("Users", Exact "Users",UserController, const True)
,("New User",Prefix "User" "new",UserController, const True)
,("List User",Prefix "User" "list",UserController, const True)
,("Sign up",Exact "Signup",UserController, not)
,("Sign up",Exact "Signup",UserController, (not . isLoggedIn))
,("Email Confirmation",Exact "Confirm",UserController, const False)
,("Password Reset",Exact "Passreset",UserController, const False)
,("
List
Package",Prefix "Package" "list",PackageController, const True)
,("
List
Categor
y
",Prefix "Category" "list",CategoryController, const True)
,("New Category",Prefix "Category" "new",CategoryController,
const True
)
,("
List
CurryModule",Prefix "CurryModule" "list",CurryModuleController, const True)
,("New CurryModule",Prefix "CurryModule" "new",CurryModuleController,
const True
)
,("Upload",Exact "Upload",UploadController, i
d
)
,("Package
s
",Prefix "Package" "list",PackageController, const True)
,("Categor
ies
",Prefix "Category" "list",CategoryController, const True)
,("New Category",Prefix "Category" "new",CategoryController,
isAdmin
)
,("CurryModule
s
",Prefix "CurryModule" "list",CurryModuleController, const True)
,("New CurryModule",Prefix "CurryModule" "new",CurryModuleController,
isAdmin
)
,("Upload",Exact "Upload",UploadController, i
sLoggedIn
)
,("Login",Exact "Login",LoginController, const False)
,("Logout",Exact "Logout",LogoutController, const False)
,("Admin", Exact "Admin", AdminController, id)
,("diff", Exact "diff", DiffController, const True)
,("diff", Exact "diffapi", DiffController, const True)
,("DiffAPI", Exact "diffapi", DiffController, const True)
,("Admin", Exact "Admin", AdminController, isAdmin)
,("default", Always, PackageController, const True)]
Masala/src/Controller/Category.curry
View file @
36fcac79
...
...
@@ -6,12 +6,14 @@ import Time
import Masala
import View.Category
import Maybe
import Controller.Shared
import System.SessionInfo
import System.Authorization
import System.AuthorizedActions
import Config.UserProcesses
import View.MasalaEntitiesToHtml
import Database.CDBI.Connection
import Controller.Shared
--- Choose the controller for a Category entity according to the URL parameter.
mainCategoryController :: Controller
...
...
@@ -125,4 +127,4 @@ addCategorizes versions category =
removeCategorizes :: [Version] -> Category -> DBAction ()
removeCategorizes versions category =
mapM_ (\t -> deleteCategorizes (categoryKey category) (versionKey t))
versions
\ No newline at end of file
versions
Masala/src/Controller/CurryModule.curry
View file @
36fcac79
...
...
@@ -6,6 +6,7 @@ import Time
import Masala
import View.CurryModule
import Maybe
import Controller.Shared
import System.SessionInfo
import System.Authorization
import System.AuthorizedActions
...
...
Masala/src/Controller/Package.curry
View file @
36fcac79
...
...
@@ -6,6 +6,7 @@ import Time
import Masala
import View.Package
import Maybe
import Controller.Shared
import System.SessionInfo
import System.Authorization
import System.AuthorizedActions
...
...
@@ -21,8 +22,8 @@ adminPackageController :: Controller
adminPackageController =
do args <- getControllerParams
case args of
["Package"] -> listPackageController
["Package", "list"] -> listPackageController
["Package"] -> listPackageController
Admin
["Package", "list"] -> listPackageController
Admin
["Package", "new"] -> newPackageController
["Package", "edit",s] ->
applyControllerOn (readPackageKey s) (runJustT . getPackage)
...
...
@@ -101,14 +102,20 @@ deletePackageT package = deletePackage package
--- Lists all Package entities with buttons to show, delete,
--- or edit an entity.
listPackageController :: Controller
listPackageController =
listPackageController
Admin
:: Controller
listPackageController
Admin
=
checkAuthorization (packageOperationAllowed ListEntities)
$ (\sinfo ->
do packages <- runQ queryAllPackages
return (listPackageView sinfo packages))
return (listPackageViewAdmin sinfo packages))
--- Shows a Package entity.
listPackageController :: Controller
listPackageController = do
packages <- runQ queryAllPackages
return (listPackageView packages)
--- Shows a Package entity.
showPackageController :: Package -> Controller
showPackageController package =
checkAuthorization (packageOperationAllowed (ShowEntity package))
...
...
@@ -154,4 +161,4 @@ showPackageByNameController pack ver = do
case thisVersion of
[version] -> showPackagePV package version versions
_ -> fail "Unknown version"
_ -> fail "Unknown package"
\ No newline at end of file
_ -> fail "Unknown package"
Masala/src/Controller/Search.curry
View file @
36fcac79
...
...
@@ -9,6 +9,7 @@ import View.Package
import View.User
import Maybe
import List
import Controller.Shared
import System.SessionInfo
import System.Authorization
import System.AuthorizedActions
...
...
@@ -100,7 +101,7 @@ listSearchController =
checkAuthorization (\_ -> return AccessGranted)
$ (\sinfo ->
do packets <- runQ $ queryCondPackage (\x -> True )
return (listPackageView sinfo packets))
return (listPackageView
Admin
sinfo packets))
------- Utility functions
...
...
@@ -111,4 +112,4 @@ caseInsensitiveCompare A comparator B =
a = map toLower A
b = map toLower B
in
a `comparator` b
\ No newline at end of file
a `comparator` b
Masala/src/Controller/Shared.curry
0 → 100644
View file @
36fcac79
module Controller.Shared (checkAuthorization) where
import System.Authorization
import System.Spicey(Controller, displayError)
import System.SessionInfo
--- Checks the results of an authoriation access.
--- If the access is granted, we proceed with the given controller
--- to which the current user session information is passed,
--- otherwise we display the access error message.
checkAuthorization :: (UserSessionInfo -> IO AccessResult)
-> (UserSessionInfo -> Controller)
-> Controller
checkAuthorization getaccess controller = do
sinfo <- getUserSessionInfo
accresult <- getaccess sinfo
case accresult of
AccessGranted -> controller sinfo
AccessDenied reason -> displayError reason
Masala/src/Controller/SpiceySystem.curry
View file @
36fcac79
...
...
@@ -20,6 +20,7 @@ import System.SessionInfo
import System.Authentication
import View.SpiceySystem
import View.Shared
import Controller.Shared
import Controller.DefaultController
-----------------------------------------------------------------------------
...
...
Masala/src/Controller/Upload.curry
View file @
36fcac79
module Controller.Upload ( mainUploadController ) where
import System.Spicey
import HTML.Base
import Time
import Masala
import View.Upload
import Maybe
import Controller.Shared
import System.PackageUpload (handleUploadNewPackageTarGz)
import System.Spicey
import System.SessionInfo
import System.Authorization
import System.AuthorizedActions
...
...
@@ -19,7 +21,6 @@ import IOExts
import Controller.DefaultController
import Directory
import qualified CPM.Package as CPM
import System.PackageUpload (handleUploadNewPackageTarGz)
--- Choose the controller for a Category entity according to the URL parameter.
mainUploadController :: Controller
...
...
Masala/src/Controller/User.curry
View file @
36fcac79
module Controller.User ( mainUserController, adminUserController ) where
import System.Spicey
import HTML.Base
import Time
import Masala
import View.User
import View.Shared
import Maybe
import List
import Char
import Controller.DefaultController
import System.SessionInfo
import Database.CDBI.Connection
import HTML.Base
import Masala
import Config.Config
--import Config.UserProcesses
import Controller.Shared
import System.Authentication
import System.Authorization
import System.AuthorizedActions
import Config.UserProcesses
import Config.Config
import View.MasalaEntitiesToHtml
import Database.CDBI.Connection
import System.Crypto
import System.Mail
import System.Spicey
import System.SessionInfo
import View.MasalaEntitiesToHtml
import View.User
import View.Shared
adminUserController :: Controller
adminUserController = do
(
url,
args) <- getControllerURL
(
_,
args) <- getControllerURL
case args of
["User"] -> listUserController -- DB Admin's user entity list
["User", "list"] -> listUserController -- DB Admin's user entity list
...
...
@@ -47,6 +49,8 @@ mainUserController = do
("Signup", []) -> signupController -- public signup
("Confirm", [s]) -> mailConfirmController s -- public confirm controller
("Passreset", []) -> passResetController -- public passreset controller
("User", [s]) -> userProfileController (urlencoded2string s) -- public user profile
("User", [s,"settings"]) -> userSettingsController (urlencoded2string s) -- user profile settings
_ -> displayError "Illegal URL"
getUserByName :: String -> IO (Maybe User)
...
...
@@ -234,8 +238,7 @@ mailConfirmController ccode = do
cTime <- getClockTime
case mbUserAndTokens of
Nothing -> -- no user in the DB has a token with this confirmation code
(setPageMessage "Email confirmation failed! Unknown confirmation code.") >>
defaultController
displayError "Email confirmation failed! Unknown confirmation code."
Just (dbUser, mailTokens, mt@(UserT expiry _)) -> -- a user has the supplied confirmation code
if (clockTimeToInt cTime) > expiry
then
...
...
@@ -263,8 +266,7 @@ mailConfirmController ccode = do
then
-- code has expired, just remove the token
(runT (updateUser (setUserToken dbUser (show (delete mt mailTokens))))) >>
(setPageMessage "This confirmation code has expired.") >>
defaultController
displayError "This confirmation code has expired."
else -- the ccode is valid, the user can now create a new password!
return $ passResetView (userName dbUser) (passResetHandler (userKey dbUser) ccode mt)
Just (dbUser, mailTokens, mt@(MailT expiry _ newMail)) ->
...
...
@@ -272,8 +274,7 @@ mailConfirmController ccode = do
then
-- code has expired, just remove the token
(runT (updateUser (setUserToken dbUser (show (delete mt mailTokens))))) >>
(setPageMessage "This confirmation code has expired.") >>
defaultController
displayError "This confirmation code has expired."
else do -- the ccode is valid, the new email address can be set!
let modifiedUser = setUserEmail dbUser newMail
runT $ updateUser modifiedUser
...
...
@@ -639,4 +640,4 @@ readMailTokens tokenField = maybe [] id (readMaybe tokenField)
splitMailToken :: String -> (UserID, String)
splitMailToken token =
let (suid, dashCode) = break (=='-') token
in (UserID (maybe (-1) id (readMaybe suid)), dropWhile (=='-') dashCode)
\ No newline at end of file
in (UserID (maybe (-1) id (readMaybe suid)), dropWhile (=='-') dashCode)
Masala/src/Controller/Version.curry
View file @
36fcac79
...
...
@@ -6,6 +6,7 @@ import Time
import Masala
import View.Version
import Maybe
import Controller.Shared
import System.SessionInfo
import System.Authorization
import System.AuthorizedActions
...
...
Masala/src/FileUpload/FileUpload.cabal
View file @
36fcac79
...
...
@@ -12,7 +12,7 @@ cabal-version: >=1.10
executable spicey.cgi
main-is: Main.hs
build-depends: base >=4.8 && <5,
process,
process
>= 1.3
,
directory >= 1.2.2 && < 1.4,
bytestring,
parsec,
...
...
Masala/src/FileUpload/Main.hs
View file @
36fcac79
{-# LANGUAGE OverloadedStrings #-}
import
System.IO
import
System.IO.Temp
import
System.Process
...
...
@@ -14,11 +15,20 @@ main = do
content_type
<-
lookupEnv
"CONTENT_TYPE"
case
content_type
of
(
Just
x
)
->
do
if
"multipart/form-data;"
`
isInfixOf
`
x
then
handleUpload
x
else
forwardToSpicey
request_uri
<-
lookupEnv
"QUERY_STRING"
case
request_uri
of
(
Just
uri
)
->
case
uri
of
"jobupload"
->
do
mpart
<-
handleUpload
x
handleJobUpload
mpart
_
->
if
"multipart/form-data;"
`
isInfixOf
`
x
then
do
mpart
<-
handleUpload
x
forwardToSpiceyWithFile
mpart
else
forwardToSpicey
_
->
forwardToSpicey
_
->
forwardToSpicey
--- Forward stdin/stdout to spicey directly
forwardToSpicey
::
IO
()
forwardToSpicey
=
do
...
...
@@ -26,8 +36,27 @@ forwardToSpicey = do
waitForProcess
handle
return
()
--- Handle a upload from the job runner
handleJobUpload
::
[
MultipartResult
]
->
IO
()
handleJobUpload
multipart
=
do
let
(
MultipartString
_
package
)
=
getPart
"Package"
let
(
MultipartString
_
version
)
=
getPart
"Version"
let
(
MultipartString
_
secret
)
=
getPart
"Secret"
let
(
MultipartFile
_
path
)
=
getPart
"File"
(
_
,
_
,
_
,
handle
)
<-
createProcess
(
proc
"tar"
[
"xzf"
,
"../../../"
++
BS
.
unpack
path
,
"--overwrite"
]){
std_out
=
NoStream
,
std_err
=
NoStream
,
cwd
=
Just
$
"packages/"
++
(
BS
.
unpack
package
)
++
"/"
++
(
BS
.
unpack
version
)
++
"/"
}
waitForProcess
handle
print
"Content-type: text/plain
\n\n
ok
\n
"
hClose
stdin
return
()
where
getPart
name
=
let
[
matchingValue
]
=
filter
(
filterKey
name
)
multipart
in
matchingValue
filterKey
name
(
MultipartFile
key
_
)
=
key
==
name
filterKey
name
(
MultipartString
key
_
)
=
key
==
name
--- Handle a multipart upload
handleUpload
::
String
->
IO
()
handleUpload
::
String
->
IO
[
MultipartResult
]
handleUpload
content_type
=
do
-- Setup handles
hSetBinaryMode
stdin
True
...
...
@@ -36,7 +65,10 @@ handleUpload content_type = do
-- Transform multipart to a regular field-based post request
let
boundary
=
drop
30
content_type
-- Todo: Use a regex?
(
MultiPart
multipart
)
<-
hGetMultipartBody
boundary
stdin
mpb
<-
mapM
showMultipartBody
multipart
mapM
showMultipartBody
multipart
forwardToSpiceyWithFile
::
[
MultipartResult
]
->
IO
()
forwardToSpiceyWithFile
mpb
=
do
parts
<-
mapM
showMultipartResult
mpb
-- Run spicey and pass arguments via stdin
(
Just
hin
,
_
,
_
,
handle
)
<-
createProcess
(
proc
"./run.cgi"
[]
){
std_out
=
UseHandle
stdout
,
std_in
=
CreatePipe
}
...
...
Masala/src/HTML/Base.curry
0 → 100644
View file @
36fcac79
This diff is collapsed.
Click to expand it.
Masala/src/HTML/CgiServer.curry
0 → 100644
View file @
36fcac79
This diff is collapsed.
Click to expand it.
Masala/src/Model/Masala.curry
View file @
36fcac79
...
...
@@ -1679,6 +1679,18 @@ getCurryModuleOrCreate name = do
let
[
m
]
=
ms
return
$
curryModuleKey
m
---
Gets
or
creates
a
new
`
Category
`
entity
getCategoryOrCreate
::
String
->
Database
.
CDBI
.
Connection
.
DBAction
CategoryID
getCategoryOrCreate
name
=
do
ms
<-
queryCondCategory
(\
x
->
categoryName
x
==
name
)
if
null
ms
then
do
m
<-
newCategory
name
""
return
$
categoryKey
m
else
do
let
[
m
]
=
ms
return
$
categoryKey
m
---
Inserts
a
new
`
CurryModule
`
entity
.
newCurryModule
::
String
->
Database
.
CDBI
.
Connection
.
DBAction
CurryModule
newCurryModule
name_p
=
...
...
Masala/src/System/Authorization.curry
View file @
36fcac79
--- This module specifies the access authorization to web pages.
module System.Authorization (
AccessType(..), AccessResult(..),
checkAuthorization,
AccessType(..), AccessResult(..),
effectivePermission, isLoggedIn, isAdmin
) where
import HTML.Base
import System.Spicey(Controller, displayError)
import System.SessionInfo
import Maybe
...
...
@@ -28,17 +27,3 @@ isAdmin sinfo = (effectivePermission sinfo) >= ADMIN
--- Get the effective user permission level from a session info
effectivePermission :: UserSessionInfo -> URole
effectivePermission = (maybe GUEST ldRole) . userLoginOfSession
--- Checks the results of an authoriation access.
--- If the access is granted, we proceed with the given controller
--- to which the current user session information is passed,
--- otherwise we display the access error message.
checkAuthorization :: (UserSessionInfo -> IO AccessResult)
-> (UserSessionInfo -> Controller)
-> Controller
checkAuthorization getaccess controller = do
sinfo <- getUserSessionInfo
accresult <- getaccess sinfo
case accresult of
AccessGranted -> controller sinfo
AccessDenied reason -> displayError reason
Masala/src/System/PackageUpload.curry
View file @
36fcac79
This diff is collapsed.
Click to expand it.
Masala/src/System/Routes.curry
View file @
36fcac79
...
...
@@ -7,14 +7,15 @@ module System.Routes
( getControllerReference, getRouteMenu )
where
import List
import Maybe
import HTML.Base
import Config.RoutesData
import System.Authentication
import System.Authorization
import System.SessionInfo
--generated in RoutesData
--type Route = (String, UrlMatch, ControllerReference)
--- Gets the reference of a controller corresponding to a given URL
--- according to the definition of all routes specified in
--- module RoutesData.
...
...
@@ -42,13 +43,13 @@ getControllerReference url = getRoutes >>= return . findControllerReference
--- `Exact` in the module RoutesData, except for "login",
--- are taken as menu entries.
getRouteMenu :: (String, [String]) -> IO [HtmlExp]
getRouteMenu controllerUrl
@(url, parameters)
= do
getRouteMenu controllerUrl = do
routes <- getRoutes
isLoggedIn
<-
is
User
LoggedIn
return $ getNavbar
isLoggedIn
routes
sinfo
<-
get
User
SessionInfo
return $ getNavbar
sinfo
routes
where
getNavbar ::
Bool
-> [Route] -> [HtmlExp]
getNavbar
isLoggedI
n routes@(_:_) =
getNavbar ::
UserSessionInfo
-> [Route] -> [HtmlExp]
getNavbar
sessio
n routes@(_:_) =
-- Curryversion of navbar and sidebar of Home.html
-- Navbar (with div wrapper)
[
...
...
@@ -60,7 +61,7 @@ getRouteMenu controllerUrl@(url, parameters) = do
, HtmlStruct "div" [("class", "collapse navbar-collapse"), ("id", "navbarSupportedContent")]
[ HtmlStruct "ul" [("class", "navbar-nav mr-auto")]
[ HtmlStruct "li" [("class", "nav-item active")]
[ HtmlStruct "div" [("id", "breadcrumbs"), ("class", "ml-xs-0 ml-md-5 mr-auto")]
[
getBreadCrumbs controllerUrl
]
[ HtmlStruct "div" [("id", "breadcrumbs"), ("class", "ml-xs-0 ml-md-5 mr-auto")]
(
getBreadCrumbs controllerUrl
)
]
]
-- SearchField + Button
...
...
@@ -70,7 +71,7 @@ getRouteMenu controllerUrl@(url, parameters) = do
]
--- Login ---
, HtmlStruct "div" [("class", "md-2 mr-5 my-2")] -- div2
[ HtmlStruct "a" [("href", if isLoggedIn then "?Logout" else "?Login"), ("style", "text-decoration: underline; color: white;")] [HtmlText (if isLoggedIn then "Logout" else "Login")]]
[ HtmlStruct "a" [("href",
(
if
(
isLoggedIn
session)
then "?Logout" else "?Login")
)
, ("style", "text-decoration: underline; color: white;")] [HtmlText (if
(
isLoggedIn
session)
then "Logout" else "Login")]]
]
-- Sidebar-toggle-button
, HtmlStruct "a" [("href", "#"), ("class", "btn bg-secondary"), ("style", "border-width: 1px; border-color: darkgrey"), ("id", "menu-toggle")]
...
...
@@ -79,7 +80,7 @@ getRouteMenu controllerUrl@(url, parameters) = do
] -- closing tag of nav
-- Sidebar
, HtmlStruct "div" [("id", "sidebar-wrapper")]
[ HtmlStruct "ul" [("class", "h-100 sidebar-nav")] (getLinks
isLoggedI
n routes)] -- closing tag of div-sidebar
[ HtmlStruct "ul" [("class", "h-100 sidebar-nav")] (getLinks
sessio
n routes)] -- closing tag of div-sidebar
]
]
getNavbar _ [] = []
...
...
@@ -87,66 +88,61 @@ getRouteMenu controllerUrl@(url, parameters) = do
--- returns all links of the RoutesList Parameter as [[HtmlStruct "li" [] [HtmlExp "href" ...]]]
--- the ouput should be something like this:
--- [HtmlStruct "li" [] [HtmlStruct "a" [("href", "?spiceyProcesses")] [HtmlText "Processes"]], [Html Struct "li" ...]
getLinks ::
Bool
-> [Route] -> [HtmlExp]
getLinks
isLoggedI
n ((name, matcher, _, loginCheck):restroutes) =
if not (loginCheck
isLoggedI
n)
then getLinks
isLoggedI
n restroutes
getLinks ::
UserSessionInfo
-> [Route] -> [HtmlExp]
getLinks
sessio
n ((name, matcher, _, loginCheck):restroutes) =
if not (loginCheck
sessio
n)
then getLinks
sessio
n restroutes
else case matcher of