Bug fixes and improvements in pgAdmin CLI. #7116

pull/7285/head
Pravesh Sharma 2024-03-14 18:12:28 +05:30 committed by GitHub
parent bece59d4b3
commit 1a02d13a28
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 122 additions and 68 deletions

View File

@ -134,6 +134,7 @@ def _iterate_categories(pref_d, label, res):
"open": True, "open": True,
"children": [], "children": [],
"value": gettext(pref_d['label']), "value": gettext(pref_d['label']),
"name": pref_d['name']
} }
for c in pref_d['categories']: for c in pref_d['categories']:

View File

@ -185,7 +185,7 @@ export default function PreferencesComponent({ ...props }) {
'id': id.toString(), 'id': id.toString(),
'label': node.label, 'label': node.label,
'_label': node.label, '_label': node.label,
'name': node.label, 'name': node.name,
'icon': '', 'icon': '',
'inode': true, 'inode': true,
'type': 2, 'type': 2,
@ -378,7 +378,7 @@ export default function PreferencesComponent({ ...props }) {
if(field.visible && _.isNull(firstElement)) { if(field.visible && _.isNull(firstElement)) {
firstElement = field; firstElement = field;
} }
field.tooltip = item._parent._metadata.data.name.toLowerCase() + ':' + item._metadata.data.name + ':' + field.name; field.labelTooltip = item._parent._metadata.data.name.toLowerCase() + ':' + item._metadata.data.name + ':' + field.name;
}); });
setLoadTree(crypto.getRandomValues(new Uint16Array(1))); setLoadTree(crypto.getRandomValues(new Uint16Array(1)));
initTreeTimeout = setTimeout(() => { initTreeTimeout = setTimeout(() => {

View File

@ -8,7 +8,7 @@
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
import React, { useContext, useEffect, useRef, useState } from 'react'; import React, { useContext, useEffect, useRef, useState } from 'react';
import { Box, makeStyles, Tab, Tabs, Tooltip } from '@material-ui/core'; import { Box, makeStyles, Tab, Tabs } from '@material-ui/core';
import _ from 'lodash'; import _ from 'lodash';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import clsx from 'clsx'; import clsx from 'clsx';
@ -363,10 +363,6 @@ export default function FormView({
]} ]}
/>; />;
if(field.tooltip) {
currentControl = <Tooltip title={field.tooltip} aria-label={field.tooltip}>{currentControl}</Tooltip>;
}
if(field.isFullTab && field.helpMessage) { if(field.isFullTab && field.helpMessage) {
currentControl = (<React.Fragment key={`coll-${field.id}`}> currentControl = (<React.Fragment key={`coll-${field.id}`}>
<FormNote key={`note-${field.id}`} text={field.helpMessage}/> <FormNote key={`note-${field.id}`} text={field.helpMessage}/>

View File

@ -212,7 +212,7 @@ const ALLOWED_PROPS_FIELD_COMMON = [
'label', 'options', 'optionsLoaded', 'controlProps', 'schema', 'inputRef', 'label', 'options', 'optionsLoaded', 'controlProps', 'schema', 'inputRef',
'visible', 'autoFocus', 'helpMessage', 'className', 'optionsReloadBasis', 'visible', 'autoFocus', 'helpMessage', 'className', 'optionsReloadBasis',
'orientation', 'isvalidate', 'fields', 'radioType', 'hideBrowseButton', 'btnName', 'hidden', 'orientation', 'isvalidate', 'fields', 'radioType', 'hideBrowseButton', 'btnName', 'hidden',
'withContainer', 'controlGridBasis', 'hasCheckbox', 'treeData', 'title' 'withContainer', 'controlGridBasis', 'hasCheckbox', 'treeData', 'labelTooltip'
]; ];
const ALLOWED_PROPS_FIELD_FORM = [ const ALLOWED_PROPS_FIELD_FORM = [

View File

@ -12,7 +12,7 @@ import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState }
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import { import {
Box, FormControl, OutlinedInput, FormHelperText, Box, FormControl, OutlinedInput, FormHelperText,
Grid, IconButton, FormControlLabel, Switch, Checkbox, useTheme, InputLabel, Paper, Select as MuiSelect, Radio, Grid, IconButton, FormControlLabel, Switch, Checkbox, useTheme, InputLabel, Paper, Select as MuiSelect, Radio, Tooltip,
} from '@material-ui/core'; } from '@material-ui/core';
import { ToggleButton, ToggleButtonGroup } from '@material-ui/lab'; import { ToggleButton, ToggleButtonGroup } from '@material-ui/lab';
import ErrorRoundedIcon from '@material-ui/icons/ErrorOutlineRounded'; import ErrorRoundedIcon from '@material-ui/icons/ErrorOutlineRounded';
@ -127,7 +127,7 @@ FormIcon.propTypes = {
}; };
/* Wrapper on any form component to add label, error indicator and help message */ /* Wrapper on any form component to add label, error indicator and help message */
export function FormInput({ children, error, className, label, helpMessage, required, testcid, lid, withContainer=true, labelGridBasis=3, controlGridBasis=9 }) { export function FormInput({ children, error, className, label, helpMessage, required, testcid, lid, withContainer=true, labelGridBasis=3, controlGridBasis=9, labelTooltip='' }) {
const classes = useStyles(); const classes = useStyles();
const cid = testcid || _.uniqueId('c'); const cid = testcid || _.uniqueId('c');
const helpid = `h${cid}`; const helpid = `h${cid}`;
@ -149,13 +149,20 @@ export function FormInput({ children, error, className, label, helpMessage, requ
</> </>
); );
} }
let labelComponent = <InputLabel id={lid} htmlFor={lid ? undefined : cid} className={clsx(classes.formLabel, error ? classes.formLabelError : null)} required={required}>
{label}
<FormIcon type={MESSAGE_TYPE.ERROR} style={{ marginLeft: 'auto', visibility: error ? 'unset' : 'hidden' }} />
</InputLabel>;
return ( return (
<Grid container spacing={0} className={className} data-testid="form-input"> <Grid container spacing={0} className={className} data-testid="form-input">
<Grid item lg={labelGridBasis} md={labelGridBasis} sm={12} xs={12}> <Grid item lg={labelGridBasis} md={labelGridBasis} sm={12} xs={12}>
<InputLabel id={lid} htmlFor={lid ? undefined : cid} className={clsx(classes.formLabel, error ? classes.formLabelError : null)} required={required}> {
{label} labelTooltip ?
<FormIcon type={MESSAGE_TYPE.ERROR} style={{ marginLeft: 'auto', visibility: error ? 'unset' : 'hidden' }} /> <Tooltip title={labelTooltip}>
</InputLabel> {labelComponent}
</Tooltip> : labelComponent
}
</Grid> </Grid>
<Grid item lg={controlGridBasis} md={controlGridBasis} sm={12} xs={12}> <Grid item lg={controlGridBasis} md={controlGridBasis} sm={12} xs={12}>
<FormControl error={Boolean(error)} fullWidth> <FormControl error={Boolean(error)} fullWidth>
@ -178,6 +185,7 @@ FormInput.propTypes = {
withContainer: PropTypes.bool, withContainer: PropTypes.bool,
labelGridBasis: PropTypes.number, labelGridBasis: PropTypes.number,
controlGridBasis: PropTypes.number, controlGridBasis: PropTypes.number,
labelTooltip: PropTypes.string
}; };
export function InputSQL({ value, options, onChange, className, controlProps, inputRef, ...props }) { export function InputSQL({ value, options, onChange, className, controlProps, inputRef, ...props }) {
@ -325,9 +333,9 @@ InputDateTimePicker.propTypes = {
controlProps: PropTypes.object, controlProps: PropTypes.object,
}; };
export function FormInputDateTimePicker({ hasError, required, label, className, helpMessage, testcid, ...props }) { export function FormInputDateTimePicker({ hasError, required, label, className, helpMessage, testcid, labelTooltip, ...props }) {
return ( return (
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}> <FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip}>
<InputDateTimePicker {...props} /> <InputDateTimePicker {...props} />
</FormInput> </FormInput>
); );
@ -342,6 +350,7 @@ FormInputDateTimePicker.propTypes = {
value: PropTypes.string, value: PropTypes.string,
controlProps: PropTypes.object, controlProps: PropTypes.object,
change: PropTypes.func, change: PropTypes.func,
labelTooltip: PropTypes.string
}; };
/* Use forwardRef to pass ref prop to OutlinedInput */ /* Use forwardRef to pass ref prop to OutlinedInput */
@ -426,9 +435,9 @@ InputText.propTypes = {
inputStyle: PropTypes.object inputStyle: PropTypes.object
}; };
export function FormInputText({ hasError, required, label, className, helpMessage, testcid, ...props }) { export function FormInputText({ hasError, required, label, className, helpMessage, testcid, labelTooltip, ...props }) {
return ( return (
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}> <FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip} >
<InputText label={label} {...props} /> <InputText label={label} {...props} />
</FormInput> </FormInput>
); );
@ -440,6 +449,7 @@ FormInputText.propTypes = {
className: CustomPropTypes.className, className: CustomPropTypes.className,
helpMessage: PropTypes.string, helpMessage: PropTypes.string,
testcid: PropTypes.string, testcid: PropTypes.string,
labelTooltip: PropTypes.string
}; };
export function InputFileSelect({ controlProps, onChange, disabled, readonly, isvalidate = false, hideBrowseButton=false,validate, ...props }) { export function InputFileSelect({ controlProps, onChange, disabled, readonly, isvalidate = false, hideBrowseButton=false,validate, ...props }) {
@ -488,10 +498,10 @@ InputFileSelect.propTypes = {
}; };
export function FormInputFileSelect({ export function FormInputFileSelect({
hasError, required, label, className, helpMessage, testcid, ...props }) { hasError, required, label, className, helpMessage, testcid, labelTooltip, ...props }) {
return ( return (
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}> <FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip}>
<InputFileSelect required={required} label={label} {...props} /> <InputFileSelect required={required} label={label} {...props} />
</FormInput> </FormInput>
); );
@ -503,6 +513,7 @@ FormInputFileSelect.propTypes = {
className: CustomPropTypes.className, className: CustomPropTypes.className,
helpMessage: PropTypes.string, helpMessage: PropTypes.string,
testcid: PropTypes.string, testcid: PropTypes.string,
labelTooltip: PropTypes.string
}; };
export function InputSwitch({ cid, helpid, value, onChange, readonly, controlProps, ...props }) { export function InputSwitch({ cid, helpid, value, onChange, readonly, controlProps, ...props }) {
@ -533,10 +544,10 @@ InputSwitch.propTypes = {
controlProps: PropTypes.object, controlProps: PropTypes.object,
}; };
export function FormInputSwitch({ hasError, required, label, className, helpMessage, testcid, withContainer, controlGridBasis, ...props }) { export function FormInputSwitch({ hasError, required, label, className, helpMessage, testcid, withContainer, controlGridBasis, labelTooltip, ...props }) {
return ( return (
<FormInput required={required} label={label} error={hasError} className={className} <FormInput required={required} label={label} error={hasError} className={className}
helpMessage={helpMessage} testcid={testcid} withContainer={withContainer} controlGridBasis={controlGridBasis}> helpMessage={helpMessage} testcid={testcid} withContainer={withContainer} controlGridBasis={controlGridBasis} labelTooltip={labelTooltip}>
<InputSwitch {...props} /> <InputSwitch {...props} />
</FormInput> </FormInput>
); );
@ -550,6 +561,7 @@ FormInputSwitch.propTypes = {
testcid: PropTypes.string, testcid: PropTypes.string,
withContainer: PropTypes.bool, withContainer: PropTypes.bool,
controlGridBasis: PropTypes.number, controlGridBasis: PropTypes.number,
labelTooltip: PropTypes.string
}; };
export function InputCheckbox({ cid, helpid, value, onChange, controlProps, readonly, labelPlacement, ...props }) { export function InputCheckbox({ cid, helpid, value, onChange, controlProps, readonly, labelPlacement, ...props }) {
@ -581,10 +593,10 @@ InputCheckbox.propTypes = {
}; };
export function FormInputCheckbox({ hasError, required, label, export function FormInputCheckbox({ hasError, required, label,
className, helpMessage, testcid, ...props }) { className, helpMessage, testcid, labelTooltip, ...props }) {
return ( return (
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}> <FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip}>
<InputCheckbox {...props} /> <InputCheckbox {...props} />
</FormInput> </FormInput>
); );
@ -596,6 +608,7 @@ FormInputCheckbox.propTypes = {
className: CustomPropTypes.className, className: CustomPropTypes.className,
helpMessage: PropTypes.string, helpMessage: PropTypes.string,
testcid: PropTypes.string, testcid: PropTypes.string,
labelTooltip: PropTypes.string
}; };
export function InputRadio({ helpid, value, onChange, controlProps, readonly, labelPlacement, ...props }) { export function InputRadio({ helpid, value, onChange, controlProps, readonly, labelPlacement, ...props }) {
@ -675,9 +688,9 @@ InputToggle.propTypes = {
}; };
export function FormInputToggle({ hasError, required, label, export function FormInputToggle({ hasError, required, label,
className, helpMessage, testcid, inputRef, ...props }) { className, helpMessage, testcid, inputRef, labelTooltip, ...props }) {
return ( return (
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}> <FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip}>
<InputToggle ref={inputRef} {...props} /> <InputToggle ref={inputRef} {...props} />
</FormInput> </FormInput>
); );
@ -689,7 +702,8 @@ FormInputToggle.propTypes = {
className: CustomPropTypes.className, className: CustomPropTypes.className,
helpMessage: PropTypes.string, helpMessage: PropTypes.string,
testcid: PropTypes.string, testcid: PropTypes.string,
inputRef: CustomPropTypes.ref inputRef: CustomPropTypes.ref,
labelTooltip: PropTypes.string
}; };
/* react-select package is used for select input /* react-select package is used for select input
@ -1022,9 +1036,9 @@ InputSelect.propTypes = {
export function FormInputSelect({ export function FormInputSelect({
hasError, required, className, label, helpMessage, testcid, ...props }) { hasError, required, className, label, helpMessage, testcid, labelTooltip, ...props }) {
return ( return (
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}> <FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip}>
<InputSelect ref={props.inputRef} {...props} /> <InputSelect ref={props.inputRef} {...props} />
</FormInput> </FormInput>
); );
@ -1036,7 +1050,8 @@ FormInputSelect.propTypes = {
className: CustomPropTypes.className, className: CustomPropTypes.className,
helpMessage: PropTypes.string, helpMessage: PropTypes.string,
testcid: PropTypes.string, testcid: PropTypes.string,
inputRef: CustomPropTypes.ref inputRef: CustomPropTypes.ref,
labelTooltip: PropTypes.string
}; };
const ColorButton = withColorPicker(PgIconButton); const ColorButton = withColorPicker(PgIconButton);
@ -1062,10 +1077,10 @@ InputColor.propTypes = {
}; };
export function FormInputColor({ export function FormInputColor({
hasError, required, className, label, helpMessage, testcid, ...props }) { hasError, required, className, label, helpMessage, testcid, labelTooltip, ...props }) {
return ( return (
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}> <FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip}>
<InputColor {...props} /> <InputColor {...props} />
</FormInput> </FormInput>
); );
@ -1076,7 +1091,8 @@ FormInputColor.propTypes = {
className: CustomPropTypes.className, className: CustomPropTypes.className,
label: PropTypes.string, label: PropTypes.string,
helpMessage: PropTypes.string, helpMessage: PropTypes.string,
testcid: PropTypes.string testcid: PropTypes.string,
labelTooltip: PropTypes.string
}; };
export function PlainString({ controlProps, value }) { export function PlainString({ controlProps, value }) {
@ -1193,10 +1209,10 @@ const useStylesKeyboardShortcut = makeStyles(() => ({
} }
})); }));
export function FormInputKeyboardShortcut({ hasError, label, className, helpMessage, onChange, ...props }) { export function FormInputKeyboardShortcut({ hasError, label, className, helpMessage, onChange, labelTooltip, ...props }) {
const classes = useStylesKeyboardShortcut(); const classes = useStylesKeyboardShortcut();
return ( return (
<FormInput label={label} error={hasError} className={clsx(classes.customRow, className)} helpMessage={helpMessage}> <FormInput label={label} error={hasError} className={clsx(classes.customRow, className)} helpMessage={helpMessage} labelTooltip={labelTooltip}>
<KeyboardShortcuts onChange={onChange} {...props} /> <KeyboardShortcuts onChange={onChange} {...props} />
</FormInput> </FormInput>
@ -1208,14 +1224,15 @@ FormInputKeyboardShortcut.propTypes = {
className: CustomPropTypes.className, className: CustomPropTypes.className,
helpMessage: PropTypes.string, helpMessage: PropTypes.string,
testcid: PropTypes.string, testcid: PropTypes.string,
onChange: PropTypes.func onChange: PropTypes.func,
labelTooltip: PropTypes.string
}; };
export function FormInputQueryThreshold({ hasError, label, className, helpMessage, testcid, onChange, ...props }) { export function FormInputQueryThreshold({ hasError, label, className, helpMessage, testcid, onChange, labelTooltip, ...props }) {
const cid = _.uniqueId('c'); const cid = _.uniqueId('c');
const helpid = `h${cid}`; const helpid = `h${cid}`;
return ( return (
<FormInput label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}> <FormInput label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip}>
<QueryThresholds cid={cid} helpid={helpid} onChange={onChange} {...props} /> <QueryThresholds cid={cid} helpid={helpid} onChange={onChange} {...props} />
</FormInput> </FormInput>
@ -1227,15 +1244,16 @@ FormInputQueryThreshold.propTypes = {
className: CustomPropTypes.className, className: CustomPropTypes.className,
helpMessage: PropTypes.string, helpMessage: PropTypes.string,
testcid: PropTypes.string, testcid: PropTypes.string,
onChange: PropTypes.func onChange: PropTypes.func,
labelTooltip: PropTypes.string
}; };
export function FormInputSelectThemes({ hasError, label, className, helpMessage, testcid, onChange, ...props }) { export function FormInputSelectThemes({ hasError, label, className, helpMessage, testcid, onChange, labelTooltip, ...props }) {
const cid = _.uniqueId('c'); const cid = _.uniqueId('c');
const helpid = `h${cid}`; const helpid = `h${cid}`;
return ( return (
<FormInput label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid}> <FormInput label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip}>
<SelectThemes cid={cid} helpid={helpid} onChange={onChange} {...props} /> <SelectThemes cid={cid} helpid={helpid} onChange={onChange} {...props} />
</FormInput> </FormInput>
); );
@ -1247,7 +1265,8 @@ FormInputSelectThemes.propTypes = {
className: CustomPropTypes.className, className: CustomPropTypes.className,
helpMessage: PropTypes.string, helpMessage: PropTypes.string,
testcid: PropTypes.string, testcid: PropTypes.string,
onChange: PropTypes.func onChange: PropTypes.func,
labelTooltip: PropTypes.string
}; };

View File

@ -27,7 +27,7 @@ const useStyles = makeStyles((theme) => ({
} }
})); }));
export default function KeyboardShortcuts({ value, onChange, fields, title }) { export default function KeyboardShortcuts({ value, onChange, fields }) {
const classes = useStyles(); const classes = useStyles();
const keyCid = _.uniqueId('c'); const keyCid = _.uniqueId('c');
const keyhelpid = `h${keyCid}`; const keyhelpid = `h${keyCid}`;
@ -91,7 +91,7 @@ export default function KeyboardShortcuts({ value, onChange, fields, title }) {
{ {
onKeyDown: onKeyDown, onKeyDown: onKeyDown,
} }
} title={title} /> }/>
</Grid> </Grid>
</Grid>; </Grid>;
} else if (element.name == 'shift') { } else if (element.name == 'shift') {
@ -128,6 +128,5 @@ export default function KeyboardShortcuts({ value, onChange, fields, title }) {
KeyboardShortcuts.propTypes = { KeyboardShortcuts.propTypes = {
value: PropTypes.object, value: PropTypes.object,
onChange: PropTypes.func, onChange: PropTypes.func,
fields: PropTypes.array, fields: PropTypes.array
title: PropTypes.string
}; };

View File

@ -17,6 +17,7 @@ from rich.console import Console
from rich.table import Table from rich.table import Table
from rich import box, print from rich import box, print
import json as jsonlib import json as jsonlib
from functools import wraps
console = Console() console = Console()
app = typer.Typer() app = typer.Typer()
@ -54,9 +55,26 @@ from flask_babel import gettext
app = typer.Typer(pretty_exceptions_show_locals=False) app = typer.Typer(pretty_exceptions_show_locals=False)
def update_sqlite_path(f):
"""
This function will behave as a decorator which will check if
sqlite path is provided and will update it in config
"""
@wraps(f)
def wrap(*args, **kwargs):
if kwargs and kwargs.get('sqlite_path') is not None:
# update the sqlite path
config.SQLITE_PATH = kwargs['sqlite_path']
return f(*args, **kwargs)
return wrap
class ManageServers: class ManageServers:
@app.command() @app.command()
@update_sqlite_path
def dump_servers(output_file: str, user: Optional[str] = None, def dump_servers(output_file: str, user: Optional[str] = None,
auth_source: Optional[str] = INTERNAL, auth_source: Optional[str] = INTERNAL,
sqlite_path: Optional[str] = None, sqlite_path: Optional[str] = None,
@ -66,10 +84,6 @@ class ManageServers:
# What user? # What user?
dump_user = user if user is not None else config.DESKTOP_USER dump_user = user if user is not None else config.DESKTOP_USER
# And the sqlite path
if sqlite_path is not None:
config.SQLITE_PATH = sqlite_path
print('----------') print('----------')
print('Dumping servers with:') print('Dumping servers with:')
print('User:', dump_user) print('User:', dump_user)
@ -85,6 +99,7 @@ class ManageServers:
print(str(e)) print(str(e))
@app.command() @app.command()
@update_sqlite_path
def load_servers(input_file: str, user: Optional[str] = None, def load_servers(input_file: str, user: Optional[str] = None,
auth_source: Optional[str] = INTERNAL, auth_source: Optional[str] = INTERNAL,
sqlite_path: Optional[str] = None, sqlite_path: Optional[str] = None,
@ -96,10 +111,6 @@ class ManageServers:
# What user? # What user?
load_user = user if user is not None else config.DESKTOP_USER load_user = user if user is not None else config.DESKTOP_USER
# And the sqlite path
if sqlite_path is not None:
config.SQLITE_PATH = sqlite_path
print('----------') print('----------')
print('Loading servers with:') print('Loading servers with:')
print('User:', load_user) print('User:', load_user)
@ -136,13 +147,15 @@ class AuthType(str, Enum):
class ManageUsers: class ManageUsers:
@app.command() @app.command()
@update_sqlite_path
def add_user(email: str, password: str, def add_user(email: str, password: str,
role: Annotated[Optional[bool], typer.Option( role: Annotated[Optional[bool], typer.Option(
"--admin/--nonadmin")] = False, "--admin/--nonadmin")] = False,
active: Annotated[Optional[bool], active: Annotated[Optional[bool],
typer.Option("--active/--inactive")] = True, typer.Option("--active/--inactive")] = True,
console: Optional[bool] = True, console: Optional[bool] = True,
json: Optional[bool] = False json: Optional[bool] = False,
sqlite_path: Optional[str] = None,
): ):
"""Add Internal user. """ """Add Internal user. """
@ -157,6 +170,7 @@ class ManageUsers:
ManageUsers.create_user(data, console, json) ManageUsers.create_user(data, console, json)
@app.command() @app.command()
@update_sqlite_path
def add_external_user(username: str, def add_external_user(username: str,
auth_source: AuthExtTypes = AuthExtTypes.oauth2, auth_source: AuthExtTypes = AuthExtTypes.oauth2,
email: Optional[str] = None, email: Optional[str] = None,
@ -167,7 +181,8 @@ class ManageUsers:
typer.Option( typer.Option(
"--active/--inactive")] = True, "--active/--inactive")] = True,
console: Optional[bool] = True, console: Optional[bool] = True,
json: Optional[bool] = False json: Optional[bool] = False,
sqlite_path: Optional[str] = None,
): ):
"""Add external user, other than Internal like """Add external user, other than Internal like
Ldap, Ouath2, Kerberos, Webserver. """ Ldap, Ouath2, Kerberos, Webserver. """
@ -182,14 +197,18 @@ class ManageUsers:
ManageUsers.create_user(data, console, json) ManageUsers.create_user(data, console, json)
@app.command() @app.command()
@update_sqlite_path
def delete_user(username: str, def delete_user(username: str,
auth_source: AuthType = AuthType.internal, auth_source: AuthType = AuthType.internal,
auto_confirm: Annotated[Optional[bool], auto_confirm: Annotated[Optional[bool],
typer.Option( typer.Option(
"--yes")] = False "--yes")] = False,
sqlite_path: Optional[str] = None,
): ):
"""Delete the user. """ """Delete the user. """
confirm_msg = "Are you sure you want to delete it?" confirm_msg = "Are you sure you want to delete it?"
if auto_confirm or typer.confirm(confirm_msg): if auto_confirm or typer.confirm(confirm_msg):
app = create_app(config.APP_NAME + '-cli') app = create_app(config.APP_NAME + '-cli')
with app.test_request_context(): with app.test_request_context():
@ -205,6 +224,7 @@ class ManageUsers:
print('Something went wrong. ' + str(msg)) print('Something went wrong. ' + str(msg))
@app.command() @app.command()
@update_sqlite_path
def update_user(email: str, def update_user(email: str,
password: Optional[str] = None, password: Optional[str] = None,
role: Annotated[Optional[bool], role: Annotated[Optional[bool],
@ -214,7 +234,8 @@ class ManageUsers:
typer.Option("--active/--inactive" typer.Option("--active/--inactive"
)] = None, )] = None,
console: Optional[bool] = True, console: Optional[bool] = True,
json: Optional[bool] = False json: Optional[bool] = False,
sqlite_path: Optional[str] = None,
): ):
"""Update internal user.""" """Update internal user."""
@ -247,19 +268,22 @@ class ManageUsers:
print('Something went wrong. ' + str(msg)) print('Something went wrong. ' + str(msg))
@app.command() @app.command()
@update_sqlite_path
def get_users(username: Optional[str] = None, def get_users(username: Optional[str] = None,
auth_source: AuthType = None, auth_source: AuthType = None,
json: Optional[bool] = False json: Optional[bool] = False,
sqlite_path: Optional[str] = None,
): ):
ManageUsers.get_users_from_db(username, auth_source, True, json) ManageUsers.get_users_from_db(username, auth_source, True, json)
@app.command()
def get_users_from_db(username: Optional[str] = None, def get_users_from_db(username: Optional[str] = None,
auth_source: AuthType = None, auth_source: AuthType = None,
console: Optional[bool] = True, console: Optional[bool] = True,
json: Optional[bool] = False json: Optional[bool] = False,
): ):
"""Get user(s) details.""" """Get user(s) details."""
app = create_app(config.APP_NAME + '-cli') app = create_app(config.APP_NAME + '-cli')
with app.test_request_context(): with app.test_request_context():
if username and auth_source: if username and auth_source:
@ -288,6 +312,7 @@ class ManageUsers:
return users_data return users_data
@app.command() @app.command()
@update_sqlite_path
def update_external_user(username: str, def update_external_user(username: str,
auth_source: AuthExtTypes = AuthExtTypes.oauth2, auth_source: AuthExtTypes = AuthExtTypes.oauth2,
email: Optional[str] = None, email: Optional[str] = None,
@ -298,7 +323,8 @@ class ManageUsers:
Optional[bool], Optional[bool],
typer.Option("--active/--inactive")] = None, typer.Option("--active/--inactive")] = None,
console: Optional[bool] = True, console: Optional[bool] = True,
json: Optional[bool] = False json: Optional[bool] = False,
sqlite_path: Optional[str] = None,
): ):
"""Update external users other than Internal like """Update external users other than Internal like
Ldap, Ouath2, Kerberos, Webserver.""" Ldap, Ouath2, Kerberos, Webserver."""
@ -320,9 +346,11 @@ class ManageUsers:
else: else:
status, msg = update_user(uid, data) status, msg = update_user(uid, data)
if status: if status:
_user = ManageUsers.get_users(username=username, _user = ManageUsers.get_users_from_db(
auth_source=auth_source, username=username,
console=False) auth_source=auth_source,
console=False
)
ManageUsers.display_user(_user[0], console, json) ManageUsers.display_user(_user[0], console, json)
else: else:
print('Something went wrong. ' + str(msg)) print('Something went wrong. ' + str(msg))
@ -399,7 +427,11 @@ class ManagePreferences:
return usr.id return usr.id
@app.command() @app.command()
def get_prefs(json: Optional[bool] = False): @update_sqlite_path
def get_prefs(json: Optional[bool] = False,
sqlite_path: Optional[str] = None,
):
return ManagePreferences.fetch_prefs() return ManagePreferences.fetch_prefs()
def fetch_prefs(id: Optional[bool] = None, json: Optional[bool] = False): def fetch_prefs(id: Optional[bool] = None, json: Optional[bool] = False):
@ -447,13 +479,16 @@ class ManagePreferences:
print(table) print(table)
@app.command() @app.command()
@update_sqlite_path
def set_prefs(username, def set_prefs(username,
pref_options: Annotated[Optional[List[str]], pref_options: Annotated[Optional[List[str]],
typer.Argument()] = None, typer.Argument()] = None,
auth_source: AuthType = AuthType.internal, auth_source: AuthType = AuthType.internal,
console: Optional[bool] = True, console: Optional[bool] = True,
json: Optional[bool] = False, json: Optional[bool] = False,
input_file: Optional[str] = None): input_file: Optional[str] = None,
sqlite_path: Optional[str] = None,
):
"""Set User preferences.""" """Set User preferences."""
if input_file: if input_file:
@ -593,5 +628,9 @@ def setup_db(app: Annotated[str, typer.Argument(
run_migration_for_sqlite() run_migration_for_sqlite()
if __name__ == "__main__": def main():
app() app()
if __name__ == "__main__":
main()