# Main Screens in the Doom TUI: Login, Loading, and Certificate Browser

> Explore Doom TUI's Login, Loading, and Certificate Browser screens built with Textual. Understand credential input, LDAP authentication, and template browsing.

- Repository: [000pp/doom](https://github.com/000pp/doom)
- Tags: deep-dive
- Published: 2026-02-22

---

**The Doom TUI implements three primary screens—LoginScreen for credential input, LoadingScreen for LDAP authentication, and MainScreen for certificate template browsing—built on the Textual framework with a stack-based navigation system.**

The Doom TUI is an open-source terminal interface built with the **Textual** framework for auditing Active Directory Certificate Services. According to the `000pp/doom` source code, the application follows a linear three-screen flow that separates credential collection, asynchronous authentication, and data visualization concerns.

## LoginScreen: LDAP Credential Collection

The **LoginScreen** serves as the application entry point, collecting server connection details required for LDAP binding.

### Implementation Details

In [`src/doom/screens/login_screen.py`](https://github.com/000pp/doom/blob/main/src/doom/screens/login_screen.py), the screen subclasses `textual.screen.Screen` and composes a form with inputs for IP address, domain, username, and password. The class implements the `compose()` method to render labels, input widgets, and action buttons:

```python

# Inside LoginScreen.on_button_pressed

if event.button.id == "login-button-login":
    login_data = {...}
    loading_screen = LoadingScreen(login_data)
    self.app.push_screen(loading_screen)

```

When the user clicks the **Login** button, the screen gathers input values into a dictionary and pushes a `LoadingScreen` instance onto the application stack. Pressing **Exit** immediately terminates the application using the `exit()` method.

### Input Validation Flow

The screen stores connection parameters in a structured dictionary that gets passed to the `LoadingScreen` constructor, ensuring credentials remain available throughout the authentication lifecycle without requiring global state.

## LoadingScreen: Asynchronous Authentication

The **LoadingScreen** handles the LDAP bind operation without blocking the UI, providing visual feedback during network operations.

### The Authentication Flow

Located in [`src/doom/screens/loading_screen.py`](https://github.com/000pp/doom/blob/main/src/doom/screens/loading_screen.py), this screen runs an asynchronous task named `authenticate_ldap` that calls `doom.protocols.ldap.get_ldap_connection`. The screen displays status messages and provides a **Cancel** button to abort the operation:

```python

# Run the Doom TUI

if __name__ == "__main__":
    from doom.__main__ import run
    run()

```

Upon successful authentication, the screen receives a `(connection, base_dn)` tuple and constructs a `MainScreen` instance with these parameters, pushing it onto the stack. On failure, it displays an error message and returns to the `LoginScreen` using `pop_screen()`.

### Error Handling Patterns

The screen manages connection timeouts and invalid credential scenarios by catching exceptions from the LDAP layer, ensuring the user returns to the login view for correction rather than experiencing a hard crash.

## MainScreen: Certificate Template Browser

The **MainScreen** displays Active Directory certificate templates retrieved via LDAP, allowing security auditors to inspect configuration details.

### Tree Widget Population

In [`src/doom/screens/main_screen.py`](https://github.com/000pp/doom/blob/main/src/doom/screens/main_screen.py), the screen builds a `Tree` widget and populates it with template names via the `enumerate_templates` function. The implementation uses lazy loading to improve performance:

```python
def add_template_details(self, template_node, template):
    combined_attrs = template.get('attributes', {})
    details_node = template_node.add("Template Details")
    for attr_name, value in sorted(combined_attrs.items()):
        # Boolean, list, and generic handling (see source for full logic)

        ...

```

When a user expands a template node, the `add_template_details` method dynamically constructs a hierarchy showing each attribute with formatted values for booleans, lists, and generic data types.

### Session Termination

The **Logout** button unbinds the LDAP connection and pops two screens from the stack, restoring the original `LoginScreen` with its previous input values preserved. This pattern maintains the screen stack integrity while returning the user to the entry point.

## Screen Navigation Architecture

The navigation follows a strict push-pop pattern managed by `textual.app.App`:

1. **Application start** – `doom.__main__.run()` creates `DoomApp` and pushes `LoginScreen` in `on_mount`
2. **Authentication** – `LoginScreen` pushes `LoadingScreen` with credential data
3. **Data access** – Successful binding pushes `MainScreen` with the active connection
4. **Return flow** – Logout pops both `MainScreen` and `LoadingScreen`, revealing `LoginScreen`

All three screens inherit from `textual.screen.Screen`, sharing lifecycle methods like `compose()`, `on_mount()`, and event handlers. This architecture provides clean separation of concerns and makes the UI extensible for additional workflow screens.

## Summary

- **LoginScreen** ([`src/doom/screens/login_screen.py`](https://github.com/000pp/doom/blob/main/src/doom/screens/login_screen.py)) collects LDAP server IP, domain, and credentials through a composed form interface.
- **LoadingScreen** ([`src/doom/screens/loading_screen.py`](https://github.com/000pp/doom/blob/main/src/doom/screens/loading_screen.py)) executes asynchronous `authenticate_ldap` calls and manages connection state transitions.
- **MainScreen** ([`src/doom/screens/main_screen.py`](https://github.com/000pp/doom/blob/main/src/doom/screens/main_screen.py)) renders certificate templates in a lazy-loaded tree widget with detailed attribute inspection.
- **Navigation** uses Textual's `push_screen()` and `pop_screen()` methods to maintain a three-level stack that preserves state between transitions.
- **Entry point** at [`src/doom/__main__.py`](https://github.com/000pp/doom/blob/main/src/doom/__main__.py) initializes the `DoomApp` and mounts the initial login view.

## Frequently Asked Questions

### What framework powers the Doom TUI screens?

The Doom TUI is built on the **Textual** framework for Python, utilizing its `Screen` class system and reactive widget model. All screens inherit from `textual.screen.Screen` and use Textual's built-in stack navigation methods.

### How does the Doom TUI handle LDAP authentication failures?

When `authenticate_ldap` fails in `LoadingScreen`, the screen catches the exception, displays an error message to the user, and calls `pop_screen()` to return to `LoginScreen` for credential correction without terminating the application.

### Can additional screens be added to the Doom TUI workflow?

Yes, because the architecture uses Textual's `push_screen()` method, new screens can be inserted between existing ones or added as modal overlays. Any new screen must subclass `textual.screen.Screen` and implement the `compose()` method to render its widget tree.

### What data structure stores the certificate template details?

The `MainScreen` stores template data as dictionaries containing an `attributes` key. The `add_template_details` method sorts these attributes alphabetically and formats them based on data type—handling booleans, lists, and single values differently for optimal readability in the terminal interface.