Separate password management into its own module

This commit is contained in:
Correl Roush 2018-02-01 22:15:02 -05:00
parent 9db12cc731
commit f4f619b354
3 changed files with 168 additions and 86 deletions

View file

@ -5,6 +5,7 @@ import Gitlab
import Html
import Html.Events as Events
import Paginated
import Pass
import Ports
import RemoteData
import Task
@ -14,22 +15,16 @@ type alias ObjectsResponse =
RemoteData.WebData (List Gitlab.Object)
type alias State =
{ client : Gitlab.Client
, repo : Gitlab.Repo
, objects : ObjectsResponse
}
type Model
= Loading
| Configuring Ports.Config
| Configured State
| Configured Pass.Model
type Msg
= Loaded (Maybe Ports.Config)
| UpdateConfig Config.Msg
| UpdatePass Pass.Msg
| SaveConfig
| Configure
| GotObjects ObjectsResponse
@ -57,15 +52,10 @@ subscriptions _ =
Ports.config Loaded
loadConfig : Ports.Config -> Maybe State
loadConfig : Ports.Config -> Maybe ( Pass.Model, Cmd Pass.Msg )
loadConfig cfg =
Maybe.map2
(\client repo ->
{ client = client
, repo = repo
, objects = RemoteData.NotAsked
}
)
Pass.init
(Config.toClient cfg)
(Config.toRepo cfg)
@ -74,13 +64,16 @@ update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case ( msg, model ) of
( Loaded loaded, Loading ) ->
( Debug.log "loaded" loaded
loaded
|> Maybe.andThen loadConfig
|> Maybe.map Configured
|> Maybe.withDefault (Configuring Config.init)
|> Debug.log "configured"
, Cmd.none
)
|> Maybe.map
(\( state, cmd ) ->
( Configured state, Cmd.map UpdatePass cmd )
)
|> Maybe.withDefault
( Configuring Config.init
, Cmd.none
)
( UpdateConfig update, Configuring cfg ) ->
( Configuring <|
@ -91,22 +84,16 @@ update msg model =
( SaveConfig, Configuring cfg ) ->
let
validated =
Maybe.map2
(\client repo ->
{ client = client
, repo = repo
, objects = RemoteData.NotAsked
}
)
Maybe.map2 Pass.init
(Config.toClient cfg)
(Config.toRepo cfg)
in
case validated of
Just state ->
Just ( state, cmd ) ->
( Configured state
, Cmd.batch
[ Ports.saveConfig cfg
, getObjects state.client state.repo
, Cmd.map UpdatePass cmd
]
)
@ -118,10 +105,14 @@ update msg model =
, Cmd.none
)
( GotObjects objects, Configured state ) ->
( Configured { state | objects = objects }
, Cmd.none
)
( UpdatePass m, Configured state ) ->
let
( newstate, cmd ) =
Pass.update m state
in
( Configured newstate
, Cmd.map UpdatePass cmd
)
_ ->
( model, Cmd.none )
@ -141,53 +132,5 @@ view model =
]
Configured state ->
Html.div []
[ Html.button [ Events.onClick Configure ] [ Html.text "Configure" ]
, Html.hr [] []
, viewFiles state.objects
]
viewFiles : ObjectsResponse -> Html.Html Msg
viewFiles data =
case data of
RemoteData.NotAsked ->
Html.div [] [ Html.text "Not loaded." ]
RemoteData.Failure _ ->
Html.div [] [ Html.text "Whoops." ]
RemoteData.Loading ->
Html.div [] [ Html.text "Loading objects..." ]
RemoteData.Success objects ->
let
files =
List.filter
(\o ->
o.objectType
== Gitlab.Blob
&& String.endsWith ".gpg" o.name
)
objects
in
Html.ul [] <|
List.map (\x -> Html.li [] [ viewFile x ]) files
viewFile : Gitlab.Object -> Html.Html Msg
viewFile file =
Html.text file.path
getConfig : Cmd Msg
getConfig =
Cmd.none
getObjects : Gitlab.Client -> Gitlab.Repo -> Cmd Msg
getObjects client repo =
Gitlab.getObjects repo client
|> Paginated.toTask
|> RemoteData.fromTask
|> Task.perform GotObjects
Html.map UpdatePass <|
Pass.view state

View file

@ -5,6 +5,7 @@ import Json.Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, required)
import Maybe.Extra
import Paginated
import RemoteData exposing (WebData)
import Task exposing (Task)
@ -109,8 +110,12 @@ getObjects repo client =
client
getFiles : Repo -> Client -> Task Http.Error (List Object)
getFiles : Repo -> Client -> Task e (WebData (List String))
getFiles repo client =
getObjects repo client
|> Paginated.toTask
|> Task.map (List.filter (\o -> o.objectType == Blob))
|> Task.map
(List.filter (.objectType >> (==) Blob))
|> Task.map
(List.map .path)
|> RemoteData.fromTask

134
src/Pass.elm Normal file
View file

@ -0,0 +1,134 @@
module Pass exposing (..)
import Dict exposing (Dict)
import Gitlab
import Html exposing (Html)
import Html.Attributes as Attr
import Html.Events as Events
import Maybe.Extra
import Paginated
import Regex
import RemoteData exposing (WebData)
import Task
type alias Pass =
List String
type alias Details =
{ password : String
, metadata : Dict String String
}
type alias Credentials =
{ password : String
, username : Maybe String
}
type alias Model =
{ client : Gitlab.Client
, repo : Gitlab.Repo
, entries : WebData (List Pass)
, filter : String
}
type Msg
= GotEntries (WebData (List Pass))
| UpdateFilter String
| Decrypt Pass
| Decrypted String
init : Gitlab.Client -> Gitlab.Repo -> ( Model, Cmd Msg )
init client repo =
( { client = client
, repo = repo
, entries = RemoteData.NotAsked
, filter = ""
}
, getEntries client repo
)
fromFilename : String -> Maybe Pass
fromFilename filename =
if String.endsWith ".gpg" filename then
String.dropRight 4 filename
|> String.split "/"
|> Just
else
Nothing
toFilename : Pass -> String
toFilename pass =
(String.join "/" pass) ++ ".gpg"
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
GotEntries entries ->
( { model | entries = entries }, Cmd.none )
UpdateFilter filter ->
( { model | filter = filter }, Cmd.none )
_ ->
( model, Cmd.none )
view : Model -> Html Msg
view model =
Html.div []
[ Html.input
[ Attr.value model.filter
, Events.onInput UpdateFilter
]
[]
, Html.hr [] []
, case model.entries of
RemoteData.NotAsked ->
Html.text "Loading"
RemoteData.Loading ->
Html.text "Loading..."
RemoteData.Failure _ ->
Html.text "Failed to load."
RemoteData.Success entries ->
Html.ul [] <|
List.map
(\x -> Html.li [] [ viewPass x ])
(filter model.filter entries)
]
filter : String -> List Pass -> List Pass
filter search entries =
let
regex =
Regex.caseInsensitive (Regex.regex search)
matches : String -> Pass -> Bool
matches search entry =
List.any (Regex.contains regex) entry
in
List.filter (matches search) entries
viewPass : Pass -> Html Msg
viewPass pass =
Html.text (String.join "/" pass)
getEntries : Gitlab.Client -> Gitlab.Repo -> Cmd Msg
getEntries client repo =
Gitlab.getFiles repo client
|> Task.map (RemoteData.map (List.map fromFilename >> Maybe.Extra.values))
|> Task.perform GotEntries