11"""
2- Collection of test cases to test connection module.
2+ Collection of test cases to test admin module.
33"""
44
55import datajoint as dj
6- from datajoint import DataJointError
7- import numpy as np
8- from . import CONN_INFO_ROOT , connection_root , connection_test
9-
10- from . import PREFIX
6+ import os
117import pymysql
128import pytest
139
10+ from . import CONN_INFO_ROOT
11+
12+
13+ @pytest .fixture ()
14+ def user_alice () -> dict :
15+ # set up - reset config, log in as root, and create a new user alice
16+ # reset dj.config manually because its state may be changed by these tests
17+ if os .path .exists (dj .settings .LOCALCONFIG ):
18+ os .remove (dj .settings .LOCALCONFIG )
19+ dj .config ["database.password" ] = os .getenv ("DJ_PASS" )
20+ root_conn = dj .conn (** CONN_INFO_ROOT , reset = True )
21+ new_credentials = dict (
22+ host = CONN_INFO_ROOT ["host" ],
23+ user = "alice" ,
24+ password = "oldpass" ,
25+ )
26+ root_conn .query (f"DROP USER IF EXISTS '{ new_credentials ['user' ]} '@'%%';" )
27+ root_conn .query (
28+ f"CREATE USER '{ new_credentials ['user' ]} '@'%%' "
29+ f"IDENTIFIED BY '{ new_credentials ['password' ]} ';"
30+ )
31+
32+ # test the connection
33+ dj .Connection (** new_credentials )
1434
15- def test_set_password_prompt_match (monkeypatch ):
35+ # return alice's credentials
36+ yield new_credentials
37+
38+ # tear down - delete the user and the local config file
39+ root_conn .query (f"DROP USER '{ new_credentials ['user' ]} '@'%%';" )
40+ if os .path .exists (dj .settings .LOCALCONFIG ):
41+ os .remove (dj .settings .LOCALCONFIG )
42+
43+
44+ def test_set_password_prompt_match (monkeypatch , user_alice : dict ):
1645 """
1746 Should be able to change the password using user prompt
1847 """
19- c = dj .conn (** CONN_INFO_ROOT )
20- c .query ("CREATE USER 'alice'@'%' IDENTIFIED BY 'pass';" )
21- # prompt responses: new password / confirm password / update local setting?
22- responses = ["newpass" , "newpass" , "yes" ]
23- monkeypatch .setattr ('getpass.getpass' , lambda _ : next (responses ))
24- monkeypatch .setattr ('input' , lambda _ : next (responses ))
48+ # reset the connection to use alice's credentials
49+ dj .conn (** user_alice , reset = True )
50+
51+ # prompts: new password / confirm password
52+ password_resp = iter (["newpass" , "newpass" ])
53+ # NOTE: because getpass.getpass is imported in datajoint.admin and used as
54+ # getpass in that module, we need to patch datajoint.admin.getpass
55+ # instead of getpass.getpass
56+ monkeypatch .setattr ("datajoint.admin.getpass" , lambda _ : next (password_resp ))
2557
58+ # respond no to prompt to update local config
59+ monkeypatch .setattr ("builtins.input" , lambda _ : "no" )
60+
61+ # reset password of user of current connection (alice)
2662 dj .set_password ()
2763
64+ # should not be able to connect with old credentials
2865 with pytest .raises (pymysql .err .OperationalError ):
29- # should not be able to log in with old credentials
30- dj .conn (host = CONN_INFO_ROOT ["host" ], user = "alice" , password = "pass" )
66+ dj .Connection (** user_alice )
3167
32- # should be able to log in with new credentials
33- dj .conn (host = CONN_INFO_ROOT ["host" ], user = "alice" , password = "newpass" )
68+ # should be able to connect with new credentials
69+ dj .Connection (host = user_alice ["host" ], user = user_alice [ "user" ] , password = "newpass" )
3470
35- assert dj .config ["database.password" ] == "newpass"
71+ # check that local config is not updated
72+ assert dj .config ["database.password" ] == os .getenv ("DJ_PASS" )
73+ assert not os .path .exists (dj .settings .LOCALCONFIG )
3674
37- def test_set_password_prompt_mismatch (monkeypatch ):
75+
76+ def test_set_password_prompt_mismatch (monkeypatch , user_alice : dict ):
3877 """
3978 Should not be able to change the password when passwords do not match
4079 """
41- pass
80+ # reset the connection to use alice's credentials
81+ dj .conn (** user_alice , reset = True )
82+
83+ # prompts: new password / confirm password
84+ password_resp = iter (["newpass" , "wrong" ])
85+ # NOTE: because getpass.getpass is imported in datajoint.admin and used as
86+ # getpass in that module, we need to patch datajoint.admin.getpass
87+ # instead of getpass.getpass
88+ monkeypatch .setattr ("datajoint.admin.getpass" , lambda _ : next (password_resp ))
89+
90+ # reset password of user of current connection (alice)
91+ # should be nop
92+ dj .set_password ()
93+
94+ # should be able to connect with old credentials
95+ dj .Connection (** user_alice )
96+
4297
43- def test_set_password_arg ( monkeypatch ):
98+ def test_set_password_args ( user_alice : dict ):
4499 """
45100 Should be able to change the password with an argument
46101 """
47- pass
102+ # reset the connection to use alice's credentials
103+ dj .conn (** user_alice , reset = True )
48104
49- def test_set_password_no_update_config (monkeypatch ):
105+ # reset password of user of current connection (alice)
106+ dj .set_password (new_password = "newpass" , update_config = False )
107+
108+ # should be able to connect with new credentials
109+ dj .Connection (host = user_alice ["host" ], user = user_alice ["user" ], password = "newpass" )
110+
111+
112+ def test_set_password_update_config (monkeypatch , user_alice : dict ):
50113 """
51- Should be able to change the password without updating local config
114+ Should be able to change the password and update local config
52115 """
53- pass
116+ # reset the connection to use alice's credentials
117+ dj .conn (** user_alice , reset = True )
118+
119+ # respond yes to prompt to update local config
120+ monkeypatch .setattr ("builtins.input" , lambda _ : "yes" )
121+
122+ # reset password of user of current connection (alice)
123+ dj .set_password (new_password = "newpass" )
124+
125+ # should be able to connect with new credentials
126+ dj .Connection (host = user_alice ["host" ], user = user_alice ["user" ], password = "newpass" )
127+
128+ # check that local config is updated
129+ # NOTE: the global config state is changed unless dj modules are reloaded
130+ # NOTE: this test is a bit unrealistic because the config user does not match
131+ # the user whose password is being updated, so the config credentials
132+ # will be invalid after update...
133+ assert dj .config ["database.password" ] == "newpass"
134+ assert os .path .exists (dj .settings .LOCALCONFIG )
135+
136+
137+ def test_set_password_conn (user_alice : dict ):
138+ """
139+ Should be able to change the password using a given connection
140+ """
141+ # create a connection with alice's credentials
142+ conn_alice = dj .Connection (** user_alice )
143+
144+ # reset password of user of alice's connection (alice) and do not update config
145+ dj .set_password (new_password = "newpass" , connection = conn_alice , update_config = False )
146+
147+ # should be able to connect with new credentials
148+ dj .Connection (host = user_alice ["host" ], user = user_alice ["user" ], password = "newpass" )
149+
150+ # check that local config is not updated
151+ assert dj .config ["database.password" ] == os .getenv ("DJ_PASS" )
152+ assert not os .path .exists (dj .settings .LOCALCONFIG )
0 commit comments