Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(cleanup) pam: Move model code into specific package #173

Merged
merged 3 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/qa.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,15 @@ jobs:
- name: Run tests (with race detector)
run: |
go test -race ./...

didrocks marked this conversation as resolved.
Show resolved Hide resolved
- name: Run PAM tests (with Address Sanitizer)
env:
# Do not optimize, keep debug symbols and frame pointer for better
# stack trace information in case of ASAN errors.
CGO_CFLAGS: "-O0 -g3 -fno-omit-frame-pointer"
run: |
# Use `-dwarflocationlists` to give ASAN a better time to unwind the stack trace
go test -asan -gcflags="-dwarflocationlists=true" ./pam/pam_test ./pam/gdm/
go test -C ./pam/internal -asan -gcflags="-dwarflocationlists=true" ./...
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Package main is the package for the PAM library
package main
package adapter

import (
"context"
Expand Down Expand Up @@ -126,7 +125,7 @@ func (m *authenticationModel) Update(msg tea.Msg) (authenticationModel, tea.Cmd)
log.Infof(context.TODO(), "isAuthenticatedResultReceived: %v", msg.access)
switch msg.access {
case responses.AuthGranted:
return *m, sendEvent(pamSuccess{brokerID: m.currentBrokerID})
return *m, sendEvent(PamSuccess{BrokerID: m.currentBrokerID})

case responses.AuthRetry:
errorMsg, err := dataToMsg(msg.msg)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

import (
"context"
Expand Down Expand Up @@ -251,7 +251,7 @@ func getAuthenticationModes(client authd.PAMClient, sessionID string, uiLayouts

authModes := gamResp.GetAuthenticationModes()
if len(authModes) == 0 {
return pamIgnore{msg: "no supported authentication mode available for this provider"}
return PamIgnore{msg: "no supported authentication mode available for this provider"}
}
log.Info(context.TODO(), authModes)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

import (
"context"
Expand Down Expand Up @@ -141,8 +141,6 @@ func (m brokerSelectionModel) Update(msg tea.Msg) (brokerSelectionModel, tea.Cmd
}

// Focus focuses this model. It always returns nil.
//
//nolint:unparam // Always returns nil.
func (m *brokerSelectionModel) Focus() tea.Cmd {
m.focused = true
return nil
Expand Down
2 changes: 1 addition & 1 deletion pam/button.go → pam/internal/adapter/button.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

import (
"fmt"
Expand Down
8 changes: 4 additions & 4 deletions pam/commands.go → pam/internal/adapter/commands.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

import (
"context"
Expand All @@ -23,7 +23,7 @@ func sendEvent(msg tea.Msg) tea.Cmd {
func startBrokerSession(client authd.PAMClient, brokerID, username string) tea.Cmd {
return func() tea.Msg {
if brokerID == "local" {
return pamIgnore{localBrokerID: brokerID}
return PamIgnore{LocalBrokerID: brokerID}
}

// Start a transaction for this user with the broker.
Expand Down Expand Up @@ -96,11 +96,11 @@ func getLayout(client authd.PAMClient, sessionID, authModeID string) tea.Cmd {
}

// quit tears down any active session and quit the main loop.
func (m *model) quit() tea.Cmd {
func (m *UIModel) quit() tea.Cmd {
if m.currentSession == nil {
return tea.Quit
}
return tea.Sequence(endSession(m.client, m.currentSession), tea.Quit)
return tea.Sequence(endSession(m.Client, m.currentSession), tea.Quit)
}

// endSession requests the broker to end the session.
Expand Down
2 changes: 1 addition & 1 deletion pam/formmodel.go → pam/internal/adapter/formmodel.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

import (
"fmt"
Expand Down
61 changes: 35 additions & 26 deletions pam/model.go → pam/internal/adapter/model.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package main
// Package adapter is the package for the PAM library
package adapter

import (
"context"
Expand Down Expand Up @@ -33,14 +34,17 @@ type sessionInfo struct {
encryptionKey string
}

// model is the global models orchestrator.
type model struct {
pamMTx pam.ModuleTransaction
client authd.PAMClient
// UIModel is the global models orchestrator.
type UIModel struct {
// PamMTx is the [pam.ModuleTransaction] used to communicate with PAM.
PamMTx pam.ModuleTransaction
// Client is the [authd.PAMClient] handle used to communicate with authd.
Client authd.PAMClient
// InteractiveTerminal whether the underlying PAM system is using an interactive terminal.
InteractiveTerminal bool

3v1n0 marked this conversation as resolved.
Show resolved Hide resolved
height int
width int
interactiveTerminal bool
height int
width int

currentSession *sessionInfo

Expand All @@ -49,7 +53,7 @@ type model struct {
authModeSelectionModel authModeSelectionModel
authenticationModel authenticationModel

exitStatus pamReturnStatus
exitStatus PamReturnStatus
}

/* global events */
Expand Down Expand Up @@ -86,27 +90,27 @@ type UILayoutReceived struct {
type SessionEnded struct{}

// Init initializes the main model orchestrator.
func (m *model) Init() tea.Cmd {
func (m *UIModel) Init() tea.Cmd {
m.exitStatus = pamError{status: pam.ErrSystem, msg: "model did not return anything"}
m.userSelectionModel = newUserSelectionModel(m.pamMTx)
m.userSelectionModel = newUserSelectionModel(m.PamMTx)
var cmds []tea.Cmd
cmds = append(cmds, m.userSelectionModel.Init())

m.brokerSelectionModel = newBrokerSelectionModel(m.client)
m.brokerSelectionModel = newBrokerSelectionModel(m.Client)
cmds = append(cmds, m.brokerSelectionModel.Init())

m.authModeSelectionModel = newAuthModeSelectionModel()
cmds = append(cmds, m.authModeSelectionModel.Init())

m.authenticationModel = newAuthenticationModel(m.client)
m.authenticationModel = newAuthenticationModel(m.Client)
cmds = append(cmds, m.authenticationModel.Init())

cmds = append(cmds, m.changeStage(stageUserSelection))
return tea.Batch(cmds...)
}

// Update handles events and actions to be done from the main model orchestrator.
func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (m *UIModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
log.Debugf(context.TODO(), "%+v", msg)

switch msg := msg.(type) {
Expand Down Expand Up @@ -141,7 +145,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.brokerSelectionModel.SetWidth(m.width)

// Exit cases
case pamReturnStatus:
case PamReturnStatus:
m.exitStatus = msg
return m, m.quit()

Expand All @@ -157,10 +161,10 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// Got user and brokers? Time to auto or manually select.
return m, tea.Sequence(
m.changeStage(stageBrokerSelection),
AutoSelectForUser(m.client, m.username()))
AutoSelectForUser(m.Client, m.username()))

case BrokerSelected:
return m, startBrokerSession(m.client, msg.BrokerID, m.username())
return m, startBrokerSession(m.Client, msg.BrokerID, m.username())

case SessionStarted:
m.currentSession = &sessionInfo{
Expand All @@ -176,7 +180,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

return m, tea.Sequence(
getAuthenticationModes(m.client, m.currentSession.sessionID, m.authModeSelectionModel.SupportedUILayouts()),
getAuthenticationModes(m.Client, m.currentSession.sessionID, m.authModeSelectionModel.SupportedUILayouts()),
m.changeStage(stageAuthModeSelection),
)

Expand All @@ -191,7 +195,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
msg: "reselection of current auth mode without current ID",
})
}
return m, getLayout(m.client, m.currentSession.sessionID, msg.ID)
return m, getLayout(m.Client, m.currentSession.sessionID, msg.ID)

case UILayoutReceived:
log.Info(context.TODO(), "UILayoutReceived")
Expand Down Expand Up @@ -220,7 +224,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

// View renders a text view of the whole UI.
func (m *model) View() string {
func (m *UIModel) View() string {
var view strings.Builder

log.Info(context.TODO(), m.currentStage())
Expand All @@ -245,7 +249,7 @@ func (m *model) View() string {
}

// currentStage returns our current stage step.
func (m *model) currentStage() stage {
func (m *UIModel) currentStage() stage {
if m.userSelectionModel.Focused() {
return stageUserSelection
}
Expand All @@ -262,7 +266,7 @@ func (m *model) currentStage() stage {
}

// changeStage returns a command acting to change the current stage and reset any previous views.
func (m *model) changeStage(s stage) tea.Cmd {
func (m *UIModel) changeStage(s stage) tea.Cmd {
switch s {
case stageUserSelection:
m.brokerSelectionModel.Blur()
Expand All @@ -271,7 +275,7 @@ func (m *model) changeStage(s stage) tea.Cmd {

// The session should be ended when going back to previous state, but we don’t quit the stage immediately
// and so, we should always ensure we cancel previous session.
return tea.Sequence(endSession(m.client, m.currentSession), m.userSelectionModel.Focus())
return tea.Sequence(endSession(m.Client, m.currentSession), m.userSelectionModel.Focus())

case stageBrokerSelection:
m.userSelectionModel.Blur()
Expand All @@ -280,7 +284,7 @@ func (m *model) changeStage(s stage) tea.Cmd {

m.authModeSelectionModel.Reset()

return tea.Sequence(endSession(m.client, m.currentSession), m.brokerSelectionModel.Focus())
return tea.Sequence(endSession(m.Client, m.currentSession), m.brokerSelectionModel.Focus())

case stageAuthModeSelection:
m.userSelectionModel.Blur()
Expand All @@ -303,12 +307,17 @@ func (m *model) changeStage(s stage) tea.Cmd {
return nil
}

// ExitStatus exposes the [PamReturnStatus] externally.
func (m *UIModel) ExitStatus() PamReturnStatus {
return m.exitStatus
}

// username returns currently selected user name.
func (m model) username() string {
func (m UIModel) username() string {
return m.userSelectionModel.Value()
}

// availableBrokers returns currently available brokers.
func (m model) availableBrokers() []*authd.ABResponse_BrokerInfo {
func (m UIModel) availableBrokers() []*authd.ABResponse_BrokerInfo {
return m.brokerSelectionModel.availableBrokers
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

import (
"fmt"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

import (
"fmt"
Expand Down
30 changes: 15 additions & 15 deletions pam/return.go → pam/internal/adapter/return.go
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
package main
package adapter

import (
"github.com/msteinert/pam/v2"
)

// Various signalling return messaging to PAM.

// pamReturnStatus is the interface that all PAM return types should implement.
type pamReturnStatus interface {
// PamReturnStatus is the interface that all PAM return types should implement.
type PamReturnStatus interface {
Message() string
}

// pamReturnError is an interface that PAM errors return types should implement.
type pamReturnError interface {
pamReturnStatus
// PamReturnError is an interface that PAM errors return types should implement.
type PamReturnError interface {
PamReturnStatus
Status() pam.Error
}

// pamSuccess signals PAM module to return with provided pam.Success and Quit tea.Model.
type pamSuccess struct {
brokerID string
// PamSuccess signals PAM module to return with provided pam.Success and Quit tea.Model.
type PamSuccess struct {
BrokerID string
msg string
}

// Message returns the message that should be sent to pam as info message.
func (p pamSuccess) Message() string {
func (p PamSuccess) Message() string {
return p.msg
}

// pamIgnore signals PAM module to return pam.Ignore and Quit tea.Model.
type pamIgnore struct {
localBrokerID string // Only set for local broker to store it globally.
// PamIgnore signals PAM module to return pam.Ignore and Quit tea.Model.
type PamIgnore struct {
LocalBrokerID string // Only set for local broker to store it globally.
msg string
}

// Status returns [pam.ErrIgnore].
func (p pamIgnore) Status() pam.Error {
func (p PamIgnore) Status() pam.Error {
return pam.ErrIgnore
}

// Message returns the message that should be sent to pam as info message.
func (p pamIgnore) Message() string {
func (p PamIgnore) Message() string {
return p.msg
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

import (
"context"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

import (
"github.com/charmbracelet/bubbles/textinput"
Expand Down
2 changes: 1 addition & 1 deletion pam/utils.go → pam/internal/adapter/utils.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package adapter

// convertTo converts an interface I value to T. It will panic (progamming error) if this is not the case.
func convertTo[T any, I any](elem I) T {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (

"github.com/msteinert/pam/v2"
"github.com/stretchr/testify/require"
"github.com/ubuntu/authd/pam/pam_test"
"github.com/ubuntu/authd/pam/internal/pam_test"
)

func TestSendToGdm(t *testing.T) {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"github.com/msteinert/pam/v2"
"github.com/stretchr/testify/require"
"github.com/ubuntu/authd/pam/pam_test"
"github.com/ubuntu/authd/pam/internal/pam_test"
)

func TestMain(t *testing.T) {
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion pam/gdm/protocol.go → pam/internal/gdm/protocol.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:generate ../../tools/generate-proto.sh -I../.. gdm.proto
//go:generate ../../../tools/generate-proto.sh -I../../.. gdm.proto

// Package gdm is the package for the GDM pam module handing.
package gdm
Expand Down
Loading
Loading