-
Notifications
You must be signed in to change notification settings - Fork 790
Description
Describe the bug
I'm unable to Backup, with a permission error, after using the path input, then reloading the page without any further action.
This seems to set last_storage
to None
, and by reloading the page i clear the JS state which would otherwise retain the correct value and cause it to be corrected in later operations.
This puts the account in a state where it cannot store/backup anything, as last_storage
stays set to None
.
This could be alleviated by explicitly switching storages, as that would fix the last_storage
value, but if this is disabled or none exist the button to switch storages does not appear.
To Reproduce
- Right click > Backup on any DB
- Click the folder icon in the "Filename" input
- In the "Select File" dialog, enter some path at the top and press (to navigate to it)
- Reload the page (important!)
- Right click > Backup on any DB
- Click the folder icon in the "Filename" input
- Enter a name in "Save As" and click "Create" (backupfilename.sql in my example)
- Notice that the "Filename" shows
None:/backupfilename.sql
- Click Backup, and the error should show. No backup is being created.
To check what is happening I ran the following after each step:
$ sqlite3 pgadmin4.db
sqlite> SELECT p.name, up.uid, up.value FROM user_preferences AS up JOIN preferences AS p ON p.id = up.pid;
user_language|1|en
last_storage|1|None
last_directory_visited|1|/
show_hidden_files|1|True
To fix it, i can run UPDATE user_preferences SET value='my_storage' WHERE pid=129 AND uid=1;
Expected behavior
I expected using the path input to never update last_storage
to an invalid value.
Error message
Access denied (None:/backupfilename.sql)
Desktop (please complete the following information):
- OS: Windows 10
- pgAdmin version: 9.9
- Mode: Server
- Browser (if running in server mode): Firefox
- Package type: Docker container
Additional context
The core issue seems to stem from the enter
handler calling openDir
without a second argument:
pgadmin4/web/pgadmin/misc/file_manager/static/js/components/FileManager.jsx
Lines 793 to 796 in 91ad54d
if(e.code === 'Enter') { | |
e.preventDefault(); | |
await openDir(path); | |
} |
openDir
seems to default to null
for storage:
pgadmin4/web/pgadmin/misc/file_manager/static/js/components/FileManager.jsx
Lines 524 to 534 in 91ad54d
const openDir = async (dirPath, changeStoragePath=null)=>{ | |
setErrorMsg(''); | |
setLoaderText('Loading...'); | |
try { | |
if(fmUtilsObj.isWinDrive(dirPath)) { | |
dirPath += fmUtilsObj.separator; | |
} | |
let newItems = await fmUtilsObj.getFolder(dirPath || fmUtilsObj.currPath, changeStoragePath); | |
setItems(newItems); | |
setPath(fmUtilsObj.currPath); | |
setTimeout(()=>{fmUtilsObj.setLastVisitedDir(dirPath || fmUtilsObj.currPath, changeStoragePath);}, 100); |
passing that null
through to setLastVisitedDir
which finally calls the API:
pgadmin4/web/pgadmin/misc/file_manager/static/js/components/FileManager.jsx
Lines 298 to 304 in 91ad54d
async setLastVisitedDir(path, ss) { | |
return this.api.post(url_for('file_manager.save_last_dir', { | |
trans_id: this.transId, | |
}), { | |
'path': path, | |
'storage_folder': ss | |
}); |
which sets the preference without any validity checks:
pgadmin4/web/pgadmin/misc/file_manager/__init__.py
Lines 307 to 314 in 91ad54d
@blueprint.route( | |
"/save_last_dir/<int:trans_id>", methods=["POST"], endpoint='save_last_dir' | |
) | |
@pga_login_required | |
def save_last_directory_visited(trans_id): | |
blueprint.last_directory_visited.set(req.json['path']) | |
blueprint.last_storage.set(req.json['storage_folder']) | |
return make_json_response(status=200) |