From 9e4b2892d55d49d7a6b8f3dad5345f9c26bd626f Mon Sep 17 00:00:00 2001 From: Ville Rantanen Date: Fri, 2 Mar 2018 14:08:40 +0200 Subject: [PATCH] reborking how shares are shown in manager --- code/app.py | 2 +- code/flees-manager.py | 89 +++++++++++++++++++++++++++++++------------ code/utils/utils.py | 10 +++++ 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/code/app.py b/code/app.py index a9f5ed8..64ca719 100644 --- a/code/app.py +++ b/code/app.py @@ -13,7 +13,7 @@ from revprox import ReverseProxied from utils.utils import * from utils.crypt import * -__FLEES_VERSION__ = "20180225.0" +__FLEES_VERSION__ = "20180302.0" app = Flask(__name__) app.config.from_object(__name__) # Read config from json ! diff --git a/code/flees-manager.py b/code/flees-manager.py index 73c8590..3dff5a7 100755 --- a/code/flees-manager.py +++ b/code/flees-manager.py @@ -19,20 +19,13 @@ def get_root_path(opts): def list_shares(shares,opts): table = [] - table.append(('Name', 'Path','Public','Password','Tokens','Upload','Overwrite','Direct','Expire','Recipient','Description')) + table.append(('Name', 'Path','Public','Password','APIToken','Upload','Overwrite','Direct','Expire','Recipient','Description')) for share in shares: public = get_or_none('public',share, False) - passtoken = '-' password = 'pass_hash' in share - if opts.show_password: - if 'pass_plain' in share: - password = share['pass_plain'] - else: - password = "" - if 'tokens' in share: - passtoken = ",".join(share['tokens']) - else: - passtoken = "" + tokens = 'tokens' in share + if tokens: + tokens = len(share['tokens']) > 0 upload = get_or_none('upload',share, False) overwrite = get_or_none('overwrite',share, True) direct = get_or_none('direct_links',share, False) if password else False @@ -43,7 +36,7 @@ def list_shares(shares,opts): share['path']+"/", public, password, - passtoken, + tokens, upload, overwrite, direct, @@ -88,8 +81,8 @@ def list_folders(shares,config): def add_share(shares, config, opts): # Make name and path safe: - opts.name = opts.name.decode('ascii','replace').replace(u'\uFFFD','_') - opts.path = opts.path.decode('ascii','replace').replace(u'\uFFFD','_') + opts.name = safe_name(opts.name) + opts.path = safe_path(opts.path) # check for share name exists already for share in shares: @@ -124,7 +117,7 @@ def add_share(shares, config, opts): 'expire': opts.expire }) - print(json.dumps(share, indent = 2, sort_keys = True)) + print_share(share, config) if opts.write: shares.append(share) shares_file = os.path.join(config['__root_path__'], opts.shares_file) @@ -143,7 +136,6 @@ def add_share(shares, config, opts): print("Share not saved anywhere.") - def check_login(share, config): import requests print("Login link") @@ -169,9 +161,6 @@ def check_login(share, config): def modify_share(shares, config, opts): - # Make name safe: - opts.name = opts.name.decode('ascii','replace').replace(u'\uFFFD','_') - print("Modifying share: %s"%( opts.name, )) found = False for i,share in enumerate(shares): @@ -180,14 +169,14 @@ def modify_share(shares, config, opts): orig_share = dict(share) if 'tokens' in share: orig_share['tokens'] = list(share['tokens']) - print(json.dumps(share, indent = 2, sort_keys = True)) + print_share(share, config) found = True break if not found: print('no such share') sys.exit(1) if opts.path != None: - share['path'] = opts.path.decode('ascii','replace').replace(u'\uFFFD','_') + share['path'] = safe_path(opts.path) for attr in ('public','upload','direct_links','overwrite'): if getattr(opts,attr) != None: share[attr] = getattr(opts,attr) == 'true' @@ -261,7 +250,7 @@ def modify_share(shares, config, opts): if not key in share: modified.append(key) print("Modified values: %s"%(", ".join(modified))) - print(json.dumps(share, indent = 2, sort_keys = True)) + print_share(share, config) if not opts.write: print("Share not saved anywhere.") @@ -289,6 +278,30 @@ def remove_share(shares,config,opts): print("Share was not actually removed. Use -w to rewrite shares file.") +def show_share(shares, config, opts): + + found = False + for share in shares: + if share['name'] != opts.name: + continue + found = True + break + if not found: + print('no such share') + sys.exit(1) + if not opts.show_password: + if 'pass_plain' in share: + share['pass_plain'] = "--HIDDEN--" + if 'pass_hash' in share: + share['pass_hash'] = "--HIDDEN--" + if 'tokens' in share: + share['tokens'] = ["--HIDDEN--"] + if not 'expire' in share: + share['expire'] = "--NEVER--" + print_share(share, config) + + + def print_rest_api(shares, config, opts): if 'public_url' not in config: print("Set public_url variable in your config.json") @@ -453,10 +466,31 @@ def print_rest_api_zip(config, share, token): )) +def print_share(share, config): + share = dict(share) + if 'tokens' in share: + share['tokens'] = list(share['tokens']) + data_folder = os.path.join(config['__root_path__'], config['data_folder']) + share_path = os.path.join(data_folder, share['path']) + share['path'] = share_path + if 'tokens' in share: + for i,token in enumerate(share['tokens']): + share['token%d'%(i+1,)] = token + del share['tokens'] + table = [('name',share['name'])] + for key in sorted(share): + if key != 'name': + table.append((key,share[key])) + print(tabulate(table)) + + #~ print(json.dumps(share, indent = 2, sort_keys = True)) + + def print_token(): print(random_token()) + def parse_options(): config_default = os.path.realpath( os.path.join( @@ -478,10 +512,13 @@ def parse_options(): subparsers = parser.add_subparsers(help='sub-command help', dest='subparser_name') ## list shares parser_list = subparsers.add_parser('list', help = "List shares") - parser_list.add_argument('-P', action="store_true", dest="show_password", default = False, - help = "Display passwords") ## list folders - parser_folders = subparsers.add_parser('folders', help = "List folders and share names") + parser_folders = subparsers.add_parser('folders', help = "List the subfolders in data folder, and their disk usage") + ## Show + parser_show = subparsers.add_parser('show', help = "Show share") + parser_show.add_argument('-P', action="store_true", dest="show_password", default = False, + help = "Display passwords") + parser_show.add_argument(dest="name") ## Remove parser_remove = subparsers.add_parser('remove', help = "Remove a share") parser_remove.add_argument(dest="name") @@ -590,6 +627,8 @@ if __name__ == "__main__": list_shares(shares,opts) elif opts.subparser_name == 'folders': list_folders(shares,config) + elif opts.subparser_name == 'show': + show_share(shares,config,opts) elif opts.subparser_name == 'remove': remove_share(shares,config,opts) elif opts.subparser_name == 'add': diff --git a/code/utils/utils.py b/code/utils/utils.py index 5b0e0ce..9d847fa 100644 --- a/code/utils/utils.py +++ b/code/utils/utils.py @@ -46,3 +46,13 @@ def get_or_none(key,d,none = None): return d[key] else: return none + +def safe_name(s): + return safe_string(s, "-_") + +def safe_path(s): + return safe_string(s, "-_/") + +def safe_string(s, valid): + """ return a safe string, replace non alnum characters with _ . all characters in valid are considered valid. """ + return "".join([c if c.isalnum() or c in valid else "_" for c in s])