github.com/safing/portbase@v0.19.5/notifications/module-mirror.go (about)

     1  package notifications
     2  
     3  import (
     4  	"github.com/safing/portbase/log"
     5  	"github.com/safing/portbase/modules"
     6  )
     7  
     8  // AttachToModule attaches the notification to a module and changes to the
     9  // notification will be reflected on the module failure status.
    10  func (n *Notification) AttachToModule(m *modules.Module) {
    11  	if m == nil {
    12  		log.Warningf("notifications: invalid usage: cannot attach %s to nil module", n.EventID)
    13  		return
    14  	}
    15  
    16  	n.lock.Lock()
    17  	defer n.lock.Unlock()
    18  
    19  	if n.State != Active {
    20  		log.Warningf("notifications: cannot attach module to inactive notification %s", n.EventID)
    21  		return
    22  	}
    23  	if n.belongsTo != nil {
    24  		log.Warningf("notifications: cannot override attached module for notification %s", n.EventID)
    25  		return
    26  	}
    27  
    28  	// Attach module.
    29  	n.belongsTo = m
    30  
    31  	// Set module failure status.
    32  	switch n.Type { //nolint:exhaustive
    33  	case Info:
    34  		m.Hint(n.EventID, n.Title, n.Message)
    35  	case Warning:
    36  		m.Warning(n.EventID, n.Title, n.Message)
    37  	case Error:
    38  		m.Error(n.EventID, n.Title, n.Message)
    39  	default:
    40  		log.Warningf("notifications: incompatible type for attaching to module in notification %s", n.EventID)
    41  		m.Error(n.EventID, n.Title, n.Message+" [incompatible notification type]")
    42  	}
    43  }
    44  
    45  // resolveModuleFailure removes the notification from the module failure status.
    46  func (n *Notification) resolveModuleFailure() {
    47  	if n.belongsTo != nil {
    48  		// Resolve failure in attached module.
    49  		n.belongsTo.Resolve(n.EventID)
    50  
    51  		// Reset attachment in order to mitigate duplicate failure resolving.
    52  		// Re-attachment is prevented by the state check when attaching.
    53  		n.belongsTo = nil
    54  	}
    55  }
    56  
    57  func init() {
    58  	modules.SetFailureUpdateNotifyFunc(mirrorModuleStatus)
    59  }
    60  
    61  func mirrorModuleStatus(moduleFailure uint8, id, title, msg string) {
    62  	// Ignore "resolve all" requests.
    63  	if id == "" {
    64  		return
    65  	}
    66  
    67  	// Get notification from storage.
    68  	n, ok := getNotification(id)
    69  	if ok {
    70  		// The notification already exists.
    71  
    72  		// Check if we should delete it.
    73  		if moduleFailure == modules.FailureNone && !n.Meta().IsDeleted() {
    74  
    75  			// Remove belongsTo, as the deletion was already triggered by the module itself.
    76  			n.Lock()
    77  			n.belongsTo = nil
    78  			n.Unlock()
    79  
    80  			n.Delete()
    81  		}
    82  
    83  		return
    84  	}
    85  
    86  	// A notification for the given ID does not yet exists, create it.
    87  	n = &Notification{
    88  		EventID: id,
    89  		Title:   title,
    90  		Message: msg,
    91  		AvailableActions: []*Action{
    92  			{
    93  				Text:    "Get Help",
    94  				Type:    ActionTypeOpenURL,
    95  				Payload: "https://safing.io/support/",
    96  			},
    97  		},
    98  	}
    99  
   100  	switch moduleFailure {
   101  	case modules.FailureNone:
   102  		return
   103  	case modules.FailureHint:
   104  		n.Type = Info
   105  		n.AvailableActions = nil
   106  	case modules.FailureWarning:
   107  		n.Type = Warning
   108  		n.ShowOnSystem = true
   109  	case modules.FailureError:
   110  		n.Type = Error
   111  		n.ShowOnSystem = true
   112  	}
   113  
   114  	Notify(n)
   115  }