diff of 0cd25fa3332ace022d37804bd07e5359d73e23fb

0cd25fa3332ace022d37804bd07e5359d73e23fb
diff --git a/elm-frontti/src/FeedView.elm b/elm-frontti/src/FeedView.elm
index fb71e69..53b6c5f 100644
--- a/elm-frontti/src/FeedView.elm
+++ b/elm-frontti/src/FeedView.elm
@@ -12,7 +12,7 @@ import Button exposing (murja_button)
 import UUID
 import Article_view exposing (formatDateTime)
 import FeedManager exposing (feedmanager)
-import Tab exposing (tabs)
+import Tab exposing (TabEntry, tabs)
 
 import Random
 
@@ -72,13 +72,10 @@ feeds feedReaderState show_archived settings zone fs new_feed metadata =
                                , checked show_archived
                                , onClick <| ShowArchivedFeedItems (not show_archived)] []
                        , text "Show read items"]
-            , tabs "rss-feed-tab" (readerState_str feedReaderState)
-                  (Dict.fromList [ ("PerFeed", "Group by feed")
-                                 , ("SingleFeed", "Show all in a feed")
-                                 , ("FeedManager", "Manage feeds")])
-                  (Dict.fromList [ ("PerFeed", perFeedView settings zone fs new_feed_state)
-                                 , ("SingleFeed", singleFeedView settings zone fs)
-                                 , ("FeedManager", feedmanager settings.time_format zone fs)])
+            , tabs "rss-feed-tab" (readerState_str feedReaderState) Nothing
+                  (Dict.fromList [ ("PerFeed", TabEntry "Group by feed" (perFeedView settings zone fs new_feed_state) Nothing ["*"])
+                                 , ("SingleFeed", TabEntry "Show all in a feed" (singleFeedView settings zone fs) Nothing ["*"])
+                                 , ("FeedManager", TabEntry "Manage feeds" (feedmanager settings.time_format zone fs) Nothing ["*"])])
                   
             , h3 [] [ text "Add new feed?"]
             , label [ for "name" ] [ text "Feed name" ]
diff --git a/elm-frontti/src/Main.elm b/elm-frontti/src/Main.elm
index e930e4c..65952fc 100644
--- a/elm-frontti/src/Main.elm
+++ b/elm-frontti/src/Main.elm
@@ -45,6 +45,7 @@ import File exposing (mime)
 
 import FeedView
 import Feeds exposing (NewFeed)
+import Tab exposing (..)
 
 -- MAIN
 
@@ -637,7 +638,6 @@ update msg model =
                                                        | show_preview = selected_tab == "PreviewArticle"})
                            model.postEditorSettings}
                     , Cmd.none)
-                
                 _ -> ( model
                      , alert <| "Unknown tab " ++ tab_id)
         ReadFeedItem feed_id item_id is_read ->
@@ -741,7 +741,76 @@ sidebarHistory titles =
                                                         [li [] [text ("There's no year " ++ (fromInt year) ++ " in titles")]]) (keys grouped_by_year |> List.reverse)))]
 
 
-
+page_wrapper comp = 
+    div [class "flex-container"] 
+        [ div [class "page"]
+              comp]
+
+blog_tab settings model =
+    div [] 
+    (case model.view_state of
+        Loading ->
+            [div [] [text "LOADING"]]
+        PostView article ->
+            [ articleView settings model.loginState model.zone article ]
+        PageView page ->
+            let post_elements = (List.map (articleView settings model.loginState model.zone) page.posts) in
+            (List.concat [ (if post_elements /= [] then
+                                post_elements
+                            else
+                                [ div [class "post"] [ text <| case model.loginState of
+                                                                   LoggedIn usr -> (Debug.toString usr)
+                                                                   _ -> "There are no (also: no user) posts in this instance"]])
+                         , [footer [ attribute "data-testid" "page-changer"
+                                   , class "page-changer" ]
+                                (if page.id > 1 then
+                                     [ a [href ("/blog/page/" ++ fromInt (page.id + 1))] [text "Older posts"]
+                                     , a [href ("/blog/page/" ++ fromInt (page.id - 1)), class "newer-post"] [text "Newer posts"]]
+                                 else
+                                     [a [href ("/blog/page/" ++ fromInt (page.id + 1))] [text "Older posts"]])]])
+        ShowError err ->
+            [pre [] [text err]]
+        TaggedPostsView articles ->
+            (List.map (articleView settings model.loginState model.zone) articles)
+        _ ->
+            [ div [] [ text "Unknown viewstate in blog_tab"] ])
+
+rss_tab model settings =
+    div []
+    (case model.view_state of
+        Feeds feeds show_archived -> [ FeedView.feeds model.feedReaderState show_archived settings model.zone feeds model.new_feed model.feedMetadata]
+        _ -> [ div [] [ text "Unknown viewstate in rss_tab"] ])
+
+postmanager_tab model =
+    div [] 
+    (case model.view_state of
+        PostEditorList titles -> [ PostsAdmin.view titles ]
+        _ -> [ div [] [ text "Unknown viewstate in postmanager_tab"] ])
+
+mediamanager_tab model =
+    div [] 
+    (case model.view_state of
+        MediaList -> [ medialist model.loadedImages model.medialist_state ]
+        _ -> [ div [] [ text "Unknown viewstate in mediamanager_tab"] ])
+
+settings_tab settings model =
+    div []
+        (case model.view_state of
+            SettingsEditor -> [ SettingsEditor.editor settings]
+            _ -> [ div [] [ text "Unknown viewstate in settings_tab"] ])
+
+posteditor_tab settings model =
+    div [ class "posteditor-tab" ]
+    (case model.view_state of 
+        PostEditor ->
+            case model.postEditorSettings of
+                Just editorSettings ->
+                    let post = editorSettings.article
+                        tag_index = editorSettings.selected_tag in
+                    PostEditor.postEditor post tag_index model.showImageModal model.loadedImages model.draggingImages editorSettings settings model.zone model.loginState model.searchedPosts
+                Nothing -> [ div [] [ text "No post loaded" ]]
+        _ -> [ div [] [ text "Unknown viewstate in posteditor_tab" ]])
+                                                              
 view : Model -> Browser.Document Msg
 view model =
     case model.settings of
@@ -753,46 +822,43 @@ view model =
             { title = settings.blog_title
             , body = 
                   [ header [] [a [href "/"] [text settings.blog_title ]]
-                  , Topbar.topbar model.loginState
-                  , div [class "flex-container"] 
-                        [ div [class "page"]
-                              (case model.view_state of
-                                           Loading ->
-                                               [div [] [text "LOADING"]]
-                                           PostView article ->
-                                               [ articleView settings model.loginState model.zone article ]
-                                           PageView page ->
-                                               let post_elements = (List.map (articleView settings model.loginState model.zone) page.posts) in
-                                               (List.concat [ (if post_elements /= [] then
-                                                                   post_elements
-                                                               else
-                                                                   [ div [class "post"] [ text "There are no posts in this instance"]])
-                                                            , [footer [ attribute "data-testid" "page-changer"
-                                                                      , class "page-changer" ]
-                                                                   (if page.id > 1 then
-                                                                        [ a [href ("/blog/page/" ++ fromInt (page.id + 1))] [text "Older posts"]
-                                                                        , a [href ("/blog/page/" ++ fromInt (page.id - 1)), class "newer-post"] [text "Newer posts"]]
-
-                                                                    else
-                                                                        [a [href ("/blog/page/" ++ fromInt (page.id + 1))] [text "Older posts"]])]])
-                                           ShowError err ->
-                                               [pre [] [text err]]
-                                           PostEditorList titles -> [ PostsAdmin.view titles ]
-                                           TaggedPostsView articles ->
-                                               (List.map (articleView settings model.loginState model.zone) articles)
-                                           PostEditor ->
-                                               case model.postEditorSettings of
-                                                   Just editorSettings ->
-                                                       let post = editorSettings.article
-                                                           tag_index = editorSettings.selected_tag in
-                                                       PostEditor.postEditor post tag_index model.showImageModal model.loadedImages model.draggingImages editorSettings settings model.zone model.loginState model.searchedPosts
-                                                   Nothing -> [ div [] [ text "No post loaded" ]]
-                                           MediaList -> [ medialist model.loadedImages model.medialist_state ]
-                                           SettingsEditor -> [ SettingsEditor.editor settings]
-                                           Feeds feeds show_archived -> [ FeedView.feeds model.feedReaderState show_archived settings model.zone feeds model.new_feed model.feedMetadata])
-                        , div [id "sidebar"] [ User.loginView model.loginState
-                                             , (sidebarHistory model.titles )
-                                             , (case model.view_state of
-                                                    PostEditorList titles -> PostsAdmin.tagList titles
-                                                    
-                                                    _ -> div [] [])]]]}
+                  , div [ class "sidebar-flex" ]
+                      [ let tabstate = viewstate_to_tabstate model.view_state in 
+                        tabs "topbar" (tabstate_to_str tabstate) (case model.loginState of
+                                                                      LoggedIn usr -> Just usr
+                                                                      _ -> Nothing)
+                            (Dict.fromList [ ("Blog"
+                                             , TabEntry "Home"
+                                                 (blog_tab settings model)
+                                                 (Just GoHome)
+                                                 ["*"])
+                                           , ("RssFeeds"
+                                             , TabEntry "RSS Feeds"
+                                                 (rss_tab model settings)
+                                                 (Just (PushUrl "/blog/feeds"))
+                                                 ["create-post"] ) -- <- TODO make a real permission for rss
+                                           , ("ManagePosts"
+                                             , TabEntry "Manage posts"
+                                                 (postmanager_tab model)
+                                                 (Just (PushUrl "/blog/postadmin"))
+                                                 ["create-post", "delete-post", "edit-post"])
+                                           , ("ManageMedia"
+                                             , TabEntry "Manage media"
+                                                 (mediamanager_tab model)
+                                                 (Just (PushUrl "/blog/mediamanager"))
+                                                 ["create-post", "delete-post", "edit-post"])
+                                           , ("SettingsTab"
+                                             , TabEntry "Settings"
+                                                 (settings_tab settings model)
+                                                 (Just (PushUrl "/blog/settings"))
+                                                 ["update-settings"])
+                                           , ("PostEditTab"
+                                             , TabEntry "Post editor"
+                                                 (posteditor_tab settings model)
+                                                 (Just GenNewPost)
+                                             ["create-post", "edit-post"])])
+                      , div [id "sidebar"] [ User.loginView model.loginState
+                                           , (sidebarHistory model.titles )
+                                           , (case model.view_state of
+                                                  PostEditorList titles -> PostsAdmin.tagList titles
+                                                  _ -> div [] [])]]]}
diff --git a/elm-frontti/src/Message.elm b/elm-frontti/src/Message.elm
index 4015a5c..cef9632 100644
--- a/elm-frontti/src/Message.elm
+++ b/elm-frontti/src/Message.elm
@@ -31,7 +31,48 @@ type ViewState
     | TaggedPostsView (List Article.Article)
     | SettingsEditor
     | Feeds (List Feeds.Feed) Bool -- <- show_archived?
-      
+
+-- a simplified version of ViewState type for the main.elm's tabcomponent 
+type TabState
+    = Blog
+    | RssFeeds
+    | ManagePosts
+    | ManageMedia
+    | SettingsTab 
+    | PostEditTab
+
+viewstate_to_tabstate vs =
+    case vs of
+        PageView _ -> Blog
+        PostView _ -> Blog
+        Loading -> Blog
+        ShowError _ -> Blog
+        PostEditorList _ -> ManagePosts
+        PostEditor -> PostEditTab
+        MediaList -> ManageMedia
+        TaggedPostsView _ -> Blog
+        SettingsEditor -> SettingsTab
+        Feeds _ _ -> RssFeeds
+
+tabstate_to_str tb =
+    case tb of
+        Blog -> "Blog"
+        RssFeeds -> "RssFeeds"
+        ManagePosts -> "ManagePosts"
+        ManageMedia -> "ManageMedia"
+        SettingsTab  -> "SettingsTab"
+        PostEditTab -> "PostEditTab"
+                       
+str_to_tabstate str =
+    case str of
+        "Blog" -> Blog
+        "RssFeeds" -> RssFeeds
+        "ManagePosts" -> ManagePosts
+        "ManageMedia" -> ManageMedia
+        "SettingsTab"  -> SettingsTab
+        "PostEditTab" -> PostEditTab
+        _ -> Blog
+
 type alias User =
     { username : String
     , nickname : String
diff --git a/elm-frontti/src/PostEditor.elm b/elm-frontti/src/PostEditor.elm
index 552e618..5b746b2 100644
--- a/elm-frontti/src/PostEditor.elm
+++ b/elm-frontti/src/PostEditor.elm
@@ -15,7 +15,7 @@ import Page as P
 import Message exposing (..)
 import ImageSelector exposing (imageSelector)
 import Button exposing (murja_button)
-import Tab exposing (tabs)
+import Tab exposing (..)
 import Dict exposing (Dict)
 
 import File exposing (File)
@@ -50,12 +50,14 @@ tagView post selectedTag = div [class "tagview editor-grouper"]
                            , murja_button [ onClick (DropTag selectedTag)
                                           , attribute "data-testid" "remove-tag"]
                                [text "Remove selected tag"]]
+
 editor params =
-    node "ace-editor"
-    (  params
-    ++ [ attribute "theme" "ace/theme/monokai"
-       , attribute "mode" "ace/mode/html"])
-    []
+    div [ class "editor-container" ]
+        [ node "ace-editor"
+             (  params
+                    ++ [ attribute "theme" "ace/theme/monokai"
+                       , attribute "mode" "ace/mode/html"])
+              []]
 
 filesDecoder : D.Decoder (List File)
 filesDecoder =
@@ -138,11 +140,10 @@ postEditor post tag showImageModal loadedImages draggingImages editorSettings ap
                 tabs "posteditor-preview-tab" (if editorSettings.show_preview then
                                                    "PreviewArticle"
                                                else
-                                                   "EditArticle")
-                    (Dict.fromList [ ("EditArticle", "Edit article")
-                                   , ("PreviewArticle", "Preview article")])
-                    (Dict.fromList [ ("EditArticle",
-                                          editor [ id "editor-post-content"
+                                                   "EditArticle") (Just user)
+                    (Dict.fromList [ ("EditArticle"
+                                     , TabEntry "Edit article"
+                                         (editor [ id "editor-post-content"
                                                  , style "background-color" (if draggingImages then "#880088" else "")
                                                  , hijackOn "dragenter" (D.succeed EditorDragEnter)
                                                  , hijackOn "dragend" (D.succeed EditorDragLeave)
@@ -150,6 +151,9 @@ postEditor post tag showImageModal loadedImages draggingImages editorSettings ap
                                                  , hijackOn "dragleave" (D.succeed EditorDragLeave)
                                                  , hijackOn "drop" dropDecoder
                                                  , hijackOn "ready" (D.succeed (RunAce post.content))])
+                                             Nothing ["*"])
                                    , ("PreviewArticle"
-                                     , Article_view.articleView app_settings loginState tz post)])
+                                     , TabEntry "Preview article"
+                                         (Article_view.articleView app_settings loginState tz post)
+                                         Nothing ["*"])])
             _ -> div [] [text "You're not logged in"]]
diff --git a/elm-frontti/src/Tab.elm b/elm-frontti/src/Tab.elm
index 695a9e5..3236694 100644
--- a/elm-frontti/src/Tab.elm
+++ b/elm-frontti/src/Tab.elm
@@ -1,21 +1,46 @@
 module Tab exposing (..)
 
 import Dict exposing (Dict)
+import Set exposing (Set)
 import Html exposing (..)
 import Html.Attributes exposing (..)
 import Html.Events exposing (..)
 import Message exposing (..)
 
--- tabs: String -> comparable -> Dict comparable String -> Dict comparable (Html msg) -> Html msg
-tabs tab_id selected_tab_key titles tabkey_to_page =
+type alias TabEntry =
+    { title: String
+    , component: Html Msg
+    , onclick: Maybe Msg
+    , permissions: List String}
+
+-- tabs: String -> String -> Dict String TabEntry -> Html Msg
+tabs tab_id selected_tab usr tabentries =
+    let tab_ids = ( tabentries
+                  |> Dict.filter (\k -> \entry -> case usr of
+                                                      Just user -> ((  entry.permissions
+                                                                    |> Set.fromList
+                                                                    |> Set.intersect (Set.fromList user.permissions)
+                                                                    |> Set.isEmpty
+                                                                    |> not)
+                                                                   ||
+                                                                        (List.member "*" entry.permissions))
+                                                      Nothing -> (List.member "*" entry.permissions))
+                  |> Dict.keys)
+        selected_tab_component = Dict.get selected_tab tabentries 
+    in 
     div [ class "tabs"
-        , id tab_id]
+        , id tab_id ]
         [ ul [ class "tab-headers" ]
-              (  titles
-              |> Dict.map
-                     (\k -> \title -> li [ class <| if selected_tab_key == k then "tab-header tab-selected" else "tab-header"
-                                         , onClick (SelectTab tab_id k)] [ text title])
-              |> Dict.values)
-        ,  (  Dict.get selected_tab_key tabkey_to_page
-           |> Maybe.withDefault (div [] [ text <| "Invalid selected tab key " ++ (Debug.toString selected_tab_key)]))]
-              
+              (  tab_ids
+              |> List.map (\id ->
+                               let entry_ = Dict.get id tabentries in
+                               case entry_ of
+                                   Just entry -> 
+                                       li [ class (if selected_tab == id then "tab-header tab-selected" else "tab-header")
+                                          , onClick (case entry.onclick of
+                                                         Just oc -> oc
+                                                         Nothing -> SelectTab tab_id id)] [ text entry.title]
+                                   Nothing -> li [] [ text "Unknown tab" ]))
+        , case selected_tab_component of
+              Just c -> c.component
+              Nothing -> div [] [ text <| "Invalid selected tab key " ++ (Debug.toString selected_tab)]]
diff --git a/resources/css/murja.css b/resources/css/murja.css
index cf9f0ed..bb72373 100644
--- a/resources/css/murja.css
+++ b/resources/css/murja.css
@@ -34,17 +34,12 @@ html, body {
 }
 
 #editor-post-content {
-    box-sizing: border-box;
-    height: 100%;
-    min-width: 100%;
     display: block;
-    flex: 10 1;	    
+    position: absolute;
+    height: 100%;
+    width: 80%;
 }
 
-/* #editor-post-save { */
-/*     flex: 1 1; */
-/* } */
-
 #editor-buttons * {
     display: block;
 }
@@ -65,7 +60,6 @@ html, body {
 
 .left-sidebar {
     flex: 1 1;
-    border: 2px solid #666666;
 }
 
 .left-sidebar > ul {
@@ -89,7 +83,6 @@ html, body {
 }
 
 .post {
-    border: 2px solid #666666;
     width: 100%;
 }
 
@@ -103,6 +96,10 @@ body, dialog {
     color: #666666;
 }
 
+.meta img {
+    margin: 1.5em;
+}
+
 .flex-container {
     display: flex;
     flex-flow: row wrap;
@@ -134,8 +131,9 @@ body, dialog {
 }
 
 #sidebar {
-    border: 2px solid #666666;
-    flex: 1 1;
+
+    margin-top: 3em;
+    width: 25%;
 }
 
 #loginview {
@@ -320,6 +318,8 @@ header {
 .tabs {
     width: 100%;
     height: 100%;
+    display: flex;
+    flex-direction: column;
 }
 
 .tab-headers {
@@ -345,6 +345,24 @@ header {
     width: 100%;
 }
 
+.sidebar-flex {
+    display: flex;
+    flex-direction: row;
+}
+
+.editor-container {
+    flex: 3;
+}
+
+.posteditor-tab {
+    display: flex;
+    flex-direction: column;
+}
+
+#posteditor-preview-tab {
+    flex: 3;
+} 
+
 @media only screen and (max-device-width:480px)
 {
     body {