github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/instance/tos.go (about)

     1  package instance
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  	"time"
     7  )
     8  
     9  // BlockingReason structs holds a reason why an instance had been blocked
    10  type BlockingReason struct {
    11  	Code    string
    12  	Message string
    13  }
    14  
    15  var (
    16  	// BlockedLoginFailed is used when a security issue has been detected on the instance
    17  	BlockedLoginFailed = BlockingReason{Code: "LOGIN_FAILED", Message: "Instance Blocked Login"}
    18  	// BlockedPaymentFailed is used when a payment is missing for the instance
    19  	BlockedPaymentFailed = BlockingReason{Code: "PAYMENT_FAILED", Message: "Instance Blocked Payment"}
    20  	// BlockedImporting is used when importing the data from another instance
    21  	BlockedImporting = BlockingReason{Code: "IMPORTING", Message: "Instance Blocked Importing"}
    22  	// BlockedMoving is used when moving data from another instance
    23  	BlockedMoving = BlockingReason{Code: "MOVING", Message: "Instance Blocked Moving"}
    24  	// BlockedUnknown is used when an instance is blocked but the reason is unknown
    25  	BlockedUnknown = BlockingReason{Code: "UNKNOWN", Message: "Instance Blocked Unknown"}
    26  )
    27  
    28  // TOSDeadline represent the state for reaching the TOS deadline.
    29  type TOSDeadline int
    30  
    31  const (
    32  	// TOSNone when no deadline is reached.
    33  	TOSNone TOSDeadline = iota
    34  	// TOSWarning when the warning deadline is reached, 2 weeks before the actual
    35  	// activation of the CGU.
    36  	TOSWarning
    37  	// TOSBlocked when the deadline is reached and the access should be blocked.
    38  	TOSBlocked
    39  )
    40  
    41  // CheckInstanceBlocked returns whether or not the instance is currently in a
    42  // blocked state: meaning it should be accessible.
    43  func (i *Instance) CheckInstanceBlocked() bool {
    44  	return i.Blocked
    45  }
    46  
    47  // CheckTOSNotSigned checks whether or not the current Term of Services have
    48  // been signed by the user.
    49  func (i *Instance) CheckTOSNotSigned(args ...string) (notSigned bool) {
    50  	notSigned, _ = i.CheckTOSNotSignedAndDeadline(args...)
    51  	return
    52  }
    53  
    54  // CheckTOSNotSignedAndDeadline checks whether or not the current Term of
    55  // Services have been signed by the user and returns the deadline state to
    56  // perform this signature.
    57  func (i *Instance) CheckTOSNotSignedAndDeadline(args ...string) (notSigned bool, deadline TOSDeadline) {
    58  	tosLatest := i.TOSLatest
    59  	if len(args) > 0 {
    60  		tosLatest = args[0]
    61  	}
    62  	latest, latestDate, ok := ParseTOSVersion(tosLatest)
    63  	if !ok || latestDate.IsZero() {
    64  		return
    65  	}
    66  	defer func() {
    67  		if notSigned {
    68  			now := time.Now()
    69  			if now.After(latestDate) {
    70  				deadline = TOSBlocked
    71  			} else if now.After(latestDate.Add(-30 * 24 * time.Hour)) {
    72  				deadline = TOSWarning
    73  			} else {
    74  				deadline = TOSNone
    75  			}
    76  		}
    77  	}()
    78  	signed, _, ok := ParseTOSVersion(i.TOSSigned)
    79  	if !ok {
    80  		notSigned = true
    81  	} else {
    82  		notSigned = signed < latest
    83  	}
    84  	return
    85  }
    86  
    87  // ParseTOSVersion returns the "major" and the date encoded in a version string
    88  // with the following format:
    89  //
    90  //	parseTOSVersion(A.B.C-YYYYMMDD) -> (A, YYYY, true)
    91  func ParseTOSVersion(v string) (major int, date time.Time, ok bool) {
    92  	if v == "" {
    93  		return
    94  	}
    95  	if len(v) == 8 {
    96  		var err error
    97  		major = 1
    98  		date, err = time.Parse("20060102", v)
    99  		ok = err == nil
   100  		return
   101  	}
   102  	if v[0] == 'v' {
   103  		v = v[1:]
   104  	}
   105  	a := strings.SplitN(v, ".", 3)
   106  	if len(a) != 3 {
   107  		return
   108  	}
   109  	major, err := strconv.Atoi(a[0])
   110  	if err != nil {
   111  		return
   112  	}
   113  	suffix := strings.SplitN(a[2], "-", 2)
   114  	if len(suffix) < 2 {
   115  		ok = true
   116  		return
   117  	}
   118  	date, err = time.Parse("20060102", suffix[1])
   119  	ok = err == nil
   120  	return
   121  }