package headscale import "gorm.io/gorm" const ( errorSameNamespace = Error("Destination namespace same as origin") errorMachineAlreadyShared = Error("Node already shared to this namespace") errorMachineNotShared = Error("Machine not shared to this namespace") ) // SharedMachine is a join table to support sharing nodes between namespaces. type SharedMachine struct { gorm.Model MachineID uint64 Machine Machine NamespaceID uint Namespace Namespace } // AddSharedMachineToNamespace adds a machine as a shared node to a namespace. func (h *Headscale) AddSharedMachineToNamespace( machine *Machine, namespace *Namespace, ) error { if machine.NamespaceID == namespace.ID { return errorSameNamespace } sharedMachines := []SharedMachine{} if err := h.db.Where("machine_id = ? AND namespace_id = ?", machine.ID, namespace.ID).Find(&sharedMachines).Error; err != nil { return err } if len(sharedMachines) > 0 { return errorMachineAlreadyShared } sharedMachine := SharedMachine{ MachineID: machine.ID, Machine: *machine, NamespaceID: namespace.ID, Namespace: *namespace, } h.db.Save(&sharedMachine) return nil } // RemoveSharedMachineFromNamespace removes a shared machine from a namespace. func (h *Headscale) RemoveSharedMachineFromNamespace( machine *Machine, namespace *Namespace, ) error { if machine.NamespaceID == namespace.ID { // Can't unshare from primary namespace return errorMachineNotShared } sharedMachine := SharedMachine{} result := h.db.Where("machine_id = ? AND namespace_id = ?", machine.ID, namespace.ID). Unscoped(). Delete(&sharedMachine) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return errorMachineNotShared } err := h.RequestMapUpdates(namespace.ID) if err != nil { return err } return nil } // RemoveSharedMachineFromAllNamespaces removes a machine as a shared node from all namespaces. func (h *Headscale) RemoveSharedMachineFromAllNamespaces(machine *Machine) error { sharedMachine := SharedMachine{} if result := h.db.Where("machine_id = ?", machine.ID).Unscoped().Delete(&sharedMachine); result.Error != nil { return result.Error } return nil }