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