permissions.mx raw

   1  package main
   2  
   3  import (
   4  	"git.smesh.lol/smesh/web/common/helpers"
   5  	"git.smesh.lol/smesh/web/common/jsbridge/ext"
   6  )
   7  
   8  // Per-host, per-method permission store.
   9  // Policies: "allow", "deny", "ask" (default when not set).
  10  
  11  type permission struct {
  12  	Host   string
  13  	Method string
  14  	Policy string
  15  }
  16  
  17  var permissions []permission
  18  
  19  func loadPermissions() {
  20  	kPerms := string(append([]byte(nil), 's', 'm', 'e', 's', 'h', '-', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 's'))
  21  	ext.StorageGet(kPerms, func(data string) {
  22  		if data != "" {
  23  			parsePermissions(data)
  24  		}
  25  	})
  26  }
  27  
  28  func getPermission(host, method string) (s string) {
  29  	for _, p := range permissions {
  30  		if p.Host == host && p.Method == method {
  31  			return p.Policy
  32  		}
  33  	}
  34  	return "ask"
  35  }
  36  
  37  func setPermission(host, method, policy string) {
  38  	for i, p := range permissions {
  39  		if p.Host == host && p.Method == method {
  40  			permissions[i].Policy = policy
  41  			savePermissions()
  42  			return
  43  		}
  44  	}
  45  	permissions = append(permissions, permission{Host: host, Method: method, Policy: policy})
  46  	savePermissions()
  47  }
  48  
  49  func savePermissions() {
  50  	b := append([]byte(nil), '[')
  51  	for i, p := range permissions {
  52  		if i > 0 {
  53  			b = append(b, ',')
  54  		}
  55  		b = append(b, '{', '"', 'h', 'o', 's', 't', '"', ':')
  56  		b = b | helpers.JsonString(p.Host)
  57  		b = append(b, ',', '"', 'm', 'e', 't', 'h', 'o', 'd', '"', ':')
  58  		b = b | helpers.JsonString(p.Method)
  59  		b = append(b, ',', '"', 'p', 'o', 'l', 'i', 'c', 'y', '"', ':')
  60  		b = b | helpers.JsonString(p.Policy)
  61  		b = append(b, '}')
  62  	}
  63  	kPerms := string(append([]byte(nil), 's', 'm', 'e', 's', 'h', '-', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 's'))
  64  	ext.StorageSet(kPerms, string(append(b, ']')))
  65  }
  66  
  67  func parsePermissions(s string) {
  68  	permissions = nil
  69  	i := 0
  70  	for i < len(s) && s[i] != '[' {
  71  		i++
  72  	}
  73  	i++
  74  	for i < len(s) {
  75  		for i < len(s) && s[i] != '{' && s[i] != ']' {
  76  			i++
  77  		}
  78  		if i >= len(s) || s[i] == ']' {
  79  			break
  80  		}
  81  		end := i + 1
  82  		depth := 1
  83  		for end < len(s) && depth > 0 {
  84  			if s[end] == '{' {
  85  				depth++
  86  			} else if s[end] == '}' {
  87  				depth--
  88  			} else if s[end] == '"' {
  89  				end++
  90  				for end < len(s) && s[end] != '"' {
  91  					if s[end] == '\\' {
  92  						end++
  93  					}
  94  					end++
  95  				}
  96  			}
  97  			end++
  98  		}
  99  		obj := s[i:end]
 100  		kHost := string(append([]byte(nil), 'h', 'o', 's', 't'))
 101  		kMethod := string(append([]byte(nil), 'm', 'e', 't', 'h', 'o', 'd'))
 102  		kPolicy := string(append([]byte(nil), 'p', 'o', 'l', 'i', 'c', 'y'))
 103  		host := helpers.JsonGetString(obj, kHost)
 104  		method := helpers.JsonGetString(obj, kMethod)
 105  		policy := helpers.JsonGetString(obj, kPolicy)
 106  		if host != "" && method != "" && policy != "" {
 107  			permissions = append(permissions, permission{Host: host, Method: method, Policy: policy})
 108  		}
 109  		i = end
 110  	}
 111  }
 112  
 113  func mgmtGetPermissions() (s string) {
 114  	b := append([]byte(nil), '{', '"', 'r', 'e', 's', 'u', 'l', 't', '"', ':', '[')
 115  	for i, p := range permissions {
 116  		if i > 0 {
 117  			b = append(b, ',')
 118  		}
 119  		b = append(b, '{', '"', 'h', 'o', 's', 't', '"', ':')
 120  		b = b | helpers.JsonString(p.Host)
 121  		b = append(b, ',', '"', 'm', 'e', 't', 'h', 'o', 'd', '"', ':')
 122  		b = b | helpers.JsonString(p.Method)
 123  		b = append(b, ',', '"', 'p', 'o', 'l', 'i', 'c', 'y', '"', ':')
 124  		b = b | helpers.JsonString(p.Policy)
 125  		b = append(b, '}')
 126  	}
 127  	return string(append(b, ']', '}'))
 128  }
 129  
 130  func mgmtSetPermission(paramsJSON string) (s string) {
 131  	kHost := string(append([]byte(nil), 'h', 'o', 's', 't'))
 132  	kMethod := string(append([]byte(nil), 'm', 'e', 't', 'h', 'o', 'd'))
 133  	kPolicy := string(append([]byte(nil), 'p', 'o', 'l', 'i', 'c', 'y'))
 134  	host := helpers.JsonGetString(paramsJSON, kHost)
 135  	method := helpers.JsonGetString(paramsJSON, kMethod)
 136  	policy := helpers.JsonGetString(paramsJSON, kPolicy)
 137  	if host == "" || method == "" || policy == "" {
 138  		return jsonErr(string(append([]byte(nil), 'm', 'i', 's', 's', 'i', 'n', 'g', ' ', 'p', 'a', 'r', 'a', 'm', 's')))
 139  	}
 140  	setPermission(host, method, policy)
 141  	return jsonTrue()
 142  }
 143  
 144  func mgmtPromptResponse(paramsJSON string) (s string) {
 145  	// TODO: handle pending prompt callbacks from content script
 146  	return jsonFalse()
 147  }
 148