Setting the file. One moment.
Test Get Admin Email · Reading Mailcatcher API · bitwarden/ai-plugins · Skills Docs
ContentsBack to the top of the page — line 87
This file
Number 42.5
Position 5 of 8
Type Python
Size 7 KB
Lines 201 scripts/tests/ test_get_admin_email.py
Python · 201 lines · 7 KB
import
unittest
15
16 HERE = os.path.dirname(os.path.abspath( __file__ ))
17 SCRIPTS = os.path.dirname( HERE )
18 sys.path.insert( 0 , SCRIPTS )
19
20 import get_admin_email
21
22 # A secrets fixture that carries admin addresses alongside unrelated secrets.
23 # The sentinel proves those other fields never reach stdout.
24 SECRETS = {
25 "adminSettings" : {
26 "admins" : "admin@localhost,owner@localhost,cs@localhost" ,
27 },
28 "globalSettings" : {
29 "sqlServer" : { "connectionString" : "Password=doNotLeakThisValue" },
30 "stripeApiKey" : "test-key-doNotLeakThisValue" ,
31 },
32 }
33
34
35 class ExtractAdminsTest ( unittest . TestCase ):
36 def test_splits_comma_separated_admins (self):
37 self .assertEqual(
38 get_admin_email.extract_admins( SECRETS ),
39 [ "admin@localhost" , "owner@localhost" , "cs@localhost" ],
40 )
41
42 def test_missing_admin_settings_raises (self):
43 with self .assertRaises(get_admin_email.SecretsError):
44 get_admin_email.extract_admins({ "other" : {}})
45
46 def test_missing_admins_key_raises (self):
47 with self .assertRaises(get_admin_email.SecretsError):
48 get_admin_email.extract_admins({ "adminSettings" : {}})
49
50 def test_empty_admins_raises (self):
51 with self .assertRaises(get_admin_email.SecretsError):
52 get_admin_email.extract_admins({ "adminSettings" : { "admins" : " , " }})
53
54 def test_non_string_admins_raises (self):
55 with self .assertRaises(get_admin_email.SecretsError):
56 get_admin_email.extract_admins({ "adminSettings" : { "admins" : [ "a@b" ]}})
57
58
59 class StripJsoncTest ( unittest . TestCase ):
60 def test_strips_line_and_block_comments_and_trailing_commas (self):
61 text = """{
62 // a leading admin
63 "adminSettings": {
64 "admins": "admin@localhost", /* the portal login */
65 },
66 }"""
67 self .assertEqual(
68 json.loads(get_admin_email.strip_jsonc(text)),
69 { "adminSettings" : { "admins" : "admin@localhost" }},
70 )
71
72 def test_preserves_comment_markers_and_commas_inside_strings (self):
73 # A // in a URL value and a , before } inside a string must survive.
74 text = '{"url": "bitwarden://checkout,}", "n": 1,}'
75 self .assertEqual(
76 json.loads(get_admin_email.strip_jsonc(text)),
77 { "url" : "bitwarden://checkout,}" , "n" : 1 },
78 )
79
80
81 def make_root (test):
82 root = tempfile.mkdtemp()
83 test.addCleanup(shutil.rmtree, root, True )
84 return root
85
86
87 def write_text (test, text, relative = os.path.join( "dev" , "secrets.json" )):
88 """Write text at <temp root>/<relative>, by default a dev/secrets.json."""
89 path = os.path.join(make_root(test), relative)
90 os.makedirs(os.path.dirname(path), exist_ok = True )
91 with open (path, "w" , encoding = "utf-8" ) as handle:
92 handle.write(text)
93 return path
94
95
96 class CheckSecretsPathTest ( unittest . TestCase ):
97 def test_dev_secrets_json_is_accepted (self):
98 get_admin_email.check_secrets_path( "/work/server/dev/secrets.json" )
99
100 def test_relative_default_is_accepted (self):
101 get_admin_email.check_secrets_path(get_admin_email. DEFAULT_SECRETS_FILE )
102
103 def test_other_file_name_is_refused (self):
104 with self .assertRaises(get_admin_email.SecretsPathError):
105 get_admin_email.check_secrets_path( "/work/server/dev/other.json" )
106
107 def test_secrets_json_outside_dev_is_refused (self):
108 with self .assertRaises(get_admin_email.SecretsPathError):
109 get_admin_email.check_secrets_path( "/etc/secrets.json" )
110
111 def test_traversal_out_of_dev_is_refused (self):
112 with self .assertRaises(get_admin_email.SecretsPathError):
113 get_admin_email.check_secrets_path( "/work/dev/secrets.json/../../.ssh/config" )
114
115 def test_symlink_named_dev_secrets_json_is_refused (self):
116 target = write_text( self , " {} " , relative = "elsewhere.json" )
117 link_dir = os.path.join(make_root( self ), "dev" )
118 os.makedirs(link_dir)
119 link = os.path.join(link_dir, "secrets.json" )
120 os.symlink(target, link)
121 with self .assertRaises(get_admin_email.SecretsPathError):
122 get_admin_email.check_secrets_path(link)
123
124
125 class MainTest ( unittest . TestCase ):
126 def _write_secrets (self, payload):
127 return write_text( self , json.dumps(payload))
128
129 def _run (self, argv):
130 out, err = io.StringIO(), io.StringIO()
131 with contextlib.redirect_stdout(out), contextlib.redirect_stderr(err):
132 code = get_admin_email.main(argv)
133 return code, out.getvalue(), err.getvalue()
134
135 def test_default_prints_only_first_admin (self):
136 path = self ._write_secrets( SECRETS )
137 code, out, _err = self ._run([ "--secrets-file" , path])
138 self .assertEqual(code, 0 )
139 self .assertEqual(out.strip(), "admin@localhost" )
140
141 def test_all_lists_every_admin (self):
142 path = self ._write_secrets( SECRETS )
143 code, out, _err = self ._run([ "--secrets-file" , path, "--all" ])
144 self .assertEqual(code, 0 )
145 self .assertEqual(
146 out.split(), [ "admin@localhost" , "owner@localhost" , "cs@localhost" ]
147 )
148
149 def test_reads_jsonc_secrets_file (self):
150 # Mirrors Bitwarden's dev secrets.json: comments and a trailing comma.
151 jsonc = """{
152 // dev admin accounts
153 "adminSettings": {
154 "admins": "admin@localhost,owner@localhost", /* portal */
155 },
156 "globalSettings": {
157 "premiumCheckoutSuccessUrl": "bitwarden://result?ok=1",
158 },
159 }"""
160 path = write_text( self , jsonc)
161 code, out, _err = self ._run([ "--secrets-file" , path, "--all" ])
162 self .assertEqual(code, 0 )
163 self .assertEqual(out.split(), [ "admin@localhost" , "owner@localhost" ])
164
165 def test_output_never_contains_other_secrets (self):
166 path = self ._write_secrets( SECRETS )
167 _code, out, _err = self ._run([ "--secrets-file" , path, "--all" ])
168 self .assertNotIn( "doNotLeakThisValue" , out)
169
170 def test_missing_file_exits_3 (self):
171 code, _out, err = self ._run([ "--secrets-file" , "/nonexistent/dev/secrets.json" ])
172 self .assertEqual(code, 3 )
173 self .assertIn( "not found" , err)
174
175 def test_invalid_json_exits_3 (self):
176 path = write_text( self , "not json" )
177 code, _out, err = self ._run([ "--secrets-file" , path])
178 self .assertEqual(code, 3 )
179 self .assertIn( "invalid JSON" , err)
180
181 def test_path_outside_dev_secrets_json_exits_2_without_reading (self):
182 # A JSON file holding an admins value proves the refusal happens before
183 # the read: were it read, its address would reach stdout.
184 path = write_text(
185 self ,
186 json.dumps({ "adminSettings" : { "admins" : "probe@localhost" }}),
187 relative = "other.json" ,
188 )
189 code, out, err = self ._run([ "--secrets-file" , path])
190 self .assertEqual(code, 2 )
191 self .assertEqual(out, "" )
192 self .assertIn( "dev/secrets.json" , err)
193
194 def test_missing_admins_key_exits_3 (self):
195 path = self ._write_secrets({ "adminSettings" : {}})
196 code, _out, _err = self ._run([ "--secrets-file" , path])
197 self .assertEqual(code, 3 )
198
199
200 if __name__ == "__main__" :
201 unittest.main()