mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-12 08:45:38 +02:00
✨ feat: Add auth flow (#146)
This adds a simple way to incorporate a centralized authentication flow. The idea is to have the user, API and SSH (for machine authentication) all in one place using `openauthjs` + `SST` We also have a database now :) > We are using InstantDB as it allows us to authenticate a use with just the email. Plus it is super simple simple to use _of course after the initial fumbles trying to design the db and relationships_
This commit is contained in:
202
packages/cli/internal/machine/machine.go
Normal file
202
packages/cli/internal/machine/machine.go
Normal file
@@ -0,0 +1,202 @@
|
||||
package machine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
)
|
||||
|
||||
type Machine struct {
|
||||
OperatingSystem string
|
||||
Arch string
|
||||
Kernel string
|
||||
Virtualization string
|
||||
Hostname string
|
||||
}
|
||||
|
||||
func NewMachine() *Machine {
|
||||
var OS string
|
||||
var architecture string
|
||||
var kernel string
|
||||
var virtualisation string
|
||||
var hostname string
|
||||
|
||||
output, _ := exec.Command("hostnamectl", "status").Output()
|
||||
os := regexp.MustCompile(`Operating System:\s+(.*)`)
|
||||
matchingOS := os.FindStringSubmatch(string(output))
|
||||
if len(matchingOS) > 1 {
|
||||
OS = matchingOS[1]
|
||||
}
|
||||
|
||||
arch := regexp.MustCompile(`Architecture:\s+(\w+)`)
|
||||
matchingArch := arch.FindStringSubmatch(string(output))
|
||||
if len(matchingArch) > 1 {
|
||||
architecture = matchingArch[1]
|
||||
}
|
||||
|
||||
kern := regexp.MustCompile(`Kernel:\s+(.*)`)
|
||||
matchingKernel := kern.FindStringSubmatch(string(output))
|
||||
if len(matchingKernel) > 1 {
|
||||
kernel = matchingKernel[1]
|
||||
}
|
||||
|
||||
virt := regexp.MustCompile(`Virtualization:\s+(\w+)`)
|
||||
matchingVirt := virt.FindStringSubmatch(string(output))
|
||||
if len(matchingVirt) > 1 {
|
||||
virtualisation = matchingVirt[1]
|
||||
}
|
||||
|
||||
host := regexp.MustCompile(`Static hostname:\s+(.*)`)
|
||||
matchingHost := host.FindStringSubmatch(string(output))
|
||||
if len(matchingHost) > 1 {
|
||||
hostname = matchingHost[1]
|
||||
}
|
||||
|
||||
return &Machine{
|
||||
OperatingSystem: OS,
|
||||
Arch: architecture,
|
||||
Kernel: kernel,
|
||||
Virtualization: virtualisation,
|
||||
Hostname: hostname,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Machine) GetOS() string {
|
||||
if m.OperatingSystem != "" {
|
||||
return m.OperatingSystem
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func (m *Machine) GetArchitecture() string {
|
||||
|
||||
if m.Arch != "" {
|
||||
return m.Arch
|
||||
}
|
||||
return "unknown"
|
||||
|
||||
}
|
||||
|
||||
func (m *Machine) GetKernel() string {
|
||||
if m.Kernel != "" {
|
||||
return m.Kernel
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func (m *Machine) GetVirtualization() string {
|
||||
if m.Virtualization != "" {
|
||||
return m.Virtualization
|
||||
}
|
||||
return "none"
|
||||
}
|
||||
|
||||
func (m *Machine) GetHostname() string {
|
||||
if m.Hostname != "" {
|
||||
return m.Hostname
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func (m *Machine) GetMachineID() string {
|
||||
id, err := os.ReadFile("/etc/machine-id")
|
||||
if err != nil {
|
||||
log.Error("Error getting your machine's ID", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return strings.TrimSpace(string(id))
|
||||
}
|
||||
|
||||
func (m *Machine) GPUInfo() (string, string, error) {
|
||||
// The command for GPU information varies depending on the system and drivers.
|
||||
// lshw is a good general-purpose tool, but might need adjustments for specific hardware.
|
||||
output, err := exec.Command("lshw", "-C", "display").Output()
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("failed to get GPU information: %w", err)
|
||||
}
|
||||
|
||||
gpuType := ""
|
||||
gpuSize := ""
|
||||
|
||||
// Regular expressions for extracting product and size information. These might need to be
|
||||
// adapted based on the output of lshw on your specific system.
|
||||
typeRegex := regexp.MustCompile(`product:\s+(.*)`)
|
||||
sizeRegex := regexp.MustCompile(`size:\s+(\d+MiB)`) // Example: extracts size in MiB
|
||||
|
||||
typeMatch := typeRegex.FindStringSubmatch(string(output))
|
||||
if len(typeMatch) > 1 {
|
||||
gpuType = typeMatch[1]
|
||||
}
|
||||
|
||||
sizeMatch := sizeRegex.FindStringSubmatch(string(output))
|
||||
if len(sizeMatch) > 1 {
|
||||
gpuSize = sizeMatch[1]
|
||||
}
|
||||
|
||||
if gpuType == "" && gpuSize == "" {
|
||||
return "", "", fmt.Errorf("could not parse GPU information using lshw")
|
||||
}
|
||||
|
||||
return gpuType, gpuSize, nil
|
||||
}
|
||||
|
||||
func (m *Machine) GetCPUInfo() (string, string, error) {
|
||||
output, err := exec.Command("lscpu").Output()
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("failed to get CPU information: %w", err)
|
||||
}
|
||||
|
||||
cpuType := ""
|
||||
cpuSize := "" // This will store the number of cores
|
||||
|
||||
typeRegex := regexp.MustCompile(`Model name:\s+(.*)`)
|
||||
coresRegex := regexp.MustCompile(`CPU\(s\):\s+(\d+)`)
|
||||
|
||||
typeMatch := typeRegex.FindStringSubmatch(string(output))
|
||||
if len(typeMatch) > 1 {
|
||||
cpuType = typeMatch[1]
|
||||
}
|
||||
|
||||
coresMatch := coresRegex.FindStringSubmatch(string(output))
|
||||
if len(coresMatch) > 1 {
|
||||
cpuSize = coresMatch[1]
|
||||
}
|
||||
|
||||
if cpuType == "" && cpuSize == "" {
|
||||
return "", "", fmt.Errorf("could not parse CPU information using lscpu")
|
||||
}
|
||||
|
||||
return cpuType, cpuSize, nil
|
||||
|
||||
}
|
||||
|
||||
func (m *Machine) GetRAMSize() (string, error) {
|
||||
output, err := exec.Command("free", "-h", "--si").Output() // Using -h for human-readable and --si for base-10 units
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get RAM information: %w", err)
|
||||
}
|
||||
|
||||
ramSize := ""
|
||||
|
||||
ramRegex := regexp.MustCompile(`Mem:\s+(\S+)`) // Matches the total memory size
|
||||
|
||||
ramMatch := ramRegex.FindStringSubmatch(string(output))
|
||||
if len(ramMatch) > 1 {
|
||||
ramSize = ramMatch[1]
|
||||
} else {
|
||||
return "", fmt.Errorf("could not parse RAM information from free command")
|
||||
}
|
||||
|
||||
return ramSize, nil
|
||||
}
|
||||
|
||||
// func cleanString(s string) string {
|
||||
// s = strings.ToLower(s)
|
||||
|
||||
// reg := regexp.MustCompile("[^a-z0-9]+") // Matches one or more non-alphanumeric characters
|
||||
// return reg.ReplaceAllString(s, "")
|
||||
// }
|
||||
Reference in New Issue
Block a user