feat: The Other Dude v9.0.1 — full-featured email system

ci: add GitHub Pages deployment workflow for docs site

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-08 17:46:37 -05:00
commit b840047e19
511 changed files with 106948 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
// Package device provides SFTP file upload helpers for RouterOS devices.
//
// RouterOS has a built-in SSH/SFTP server (port 22) that accepts the same
// credentials as the API. Since the RouterOS binary API cannot upload files,
// SFTP is used to push certificate PEM files before importing them.
package device
import (
"fmt"
"time"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
)
// NewSSHClient creates an SSH connection to a RouterOS device.
// Uses password authentication (same credentials as API access).
func NewSSHClient(ip string, port int, username, password string, timeout time.Duration) (*ssh.Client, error) {
config := &ssh.ClientConfig{
User: username,
Auth: []ssh.AuthMethod{
ssh.Password(password),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(), //nolint:gosec // RouterOS self-signed SSH
Timeout: timeout,
}
addr := fmt.Sprintf("%s:%d", ip, port)
client, err := ssh.Dial("tcp", addr, config)
if err != nil {
return nil, fmt.Errorf("SSH dial to %s: %w", addr, err)
}
return client, nil
}
// UploadFile uploads data to a file on the RouterOS device via SFTP.
func UploadFile(sshClient *ssh.Client, remotePath string, data []byte) error {
client, err := sftp.NewClient(sshClient)
if err != nil {
return fmt.Errorf("creating SFTP client: %w", err)
}
defer client.Close()
f, err := client.Create(remotePath)
if err != nil {
return fmt.Errorf("creating remote file %s: %w", remotePath, err)
}
defer f.Close()
if _, err := f.Write(data); err != nil {
return fmt.Errorf("writing to %s: %w", remotePath, err)
}
return nil
}