1- import argparse
1+ import csv
22import os
3+ import time
4+ from datetime import datetime
5+ from typing import Annotated
6+
7+ import questionary
8+ import typer
9+ from rich import print
10+ from rich .console import Console
11+ from rich .progress import Progress , SpinnerColumn , TextColumn
12+ from rich .prompt import Prompt
13+ from rich .table import Table
314
4- from libwardenpy .colors import colored_string , print_colored
515from libwardenpy .db import get_connection
616from libwardenpy .funtionality import (
717 AuthenticatedData ,
1424 list_passwords ,
1525 register_user ,
1626)
17- from libwardenpy .migrations import migrate_DB
1827from libwardenpy .passgen import generate_password
1928
2029authenticated = False
2130
2231data : UnAuthData = UnAuthData ("" , "" )
2332auth_data : AuthenticatedData = AuthenticatedData ("" , b"" )
2433
34+ app = typer .Typer ()
35+
36+
37+ @app .command ()
38+ def login (
39+ username : Annotated [
40+ str ,
41+ typer .Option ("--username" , "-u" ),
42+ ],
43+ password : Annotated [
44+ str ,
45+ typer .Option ("--password" , "-p" , prompt = True , hide_input = True ),
46+ ],
47+ ):
48+ global authenticated , auth_data , data
49+ data .username = username
50+ data .master_password = password
51+ auth_data .username = username
52+ key = authenticate_user (get_connection (), data )
53+ if key is not None :
54+ auth_data .key = key
55+ authenticated = True
56+ main ()
57+
2558
26- def init_store (args ) -> None :
59+ @app .command ()
60+ def create (
61+ username : str ,
62+ password : Annotated [
63+ str ,
64+ typer .Option (
65+ "--password" , "-p" , prompt = True , confirmation_prompt = True , hide_input = True
66+ ),
67+ ],
68+ ):
2769 global data
28- migrate_DB ()
29- USER_NAME_EXIST = False
70+ data .username , data .master_password = username , password
3071 with get_connection () as conn :
31- cursor = conn .execute ("SELECT username FROM users;" )
32- data .username = args .username
33- if (data .username ,) in cursor .fetchall ():
34- USER_NAME_EXIST = True
35- if not USER_NAME_EXIST :
36- tips_text1 = (
37- "create a strong and memorable password\n "
38- "guide: https://anonymousplanet.org/guide.html#appendix-a2-guidelines-for-passwords-and-passphrases\n "
72+ cursor = conn .execute (
73+ "SELECT COUNT(*) FROM users WHERE username = ?" , (username ,)
3974 )
40- print_colored (tips_text1 , "red" )
41- data .master_password = input ("Create Strong and Memorable Master Password: " )
42- register_user (get_connection (), data )
43- else :
44- print ("Username exit" )
45- exit ()
75+
76+ if cursor .fetchone ()[0 ] == 0 :
77+ if register_user (get_connection (), data ):
78+ print (f"User { username } registered successfully!" )
79+ else :
80+ print ("Username exists" )
81+
82+
83+ @app .command ()
84+ def export (
85+ username : str ,
86+ password : Annotated [
87+ str ,
88+ typer .Option (
89+ "--password" , "-p" , prompt = True , confirmation_prompt = True , hide_input = True
90+ ),
91+ ],
92+ ):
93+ global authenticated , auth_data , data
94+ data .username = username
95+ data .master_password = password
96+ auth_data .username = username
97+ key = authenticate_user (get_connection (), data )
98+ if key is not None :
99+ auth_data .key = key
100+ authenticated = True
101+ passwords = list_passwords (get_connection (), auth_data )
102+ if passwords is not None :
103+ with Progress (
104+ SpinnerColumn (),
105+ TextColumn ("[progress.description]{task.description}" ),
106+ transient = True ,
107+ ) as progress :
108+ progress .add_task (description = "Writing data to csv..." , total = None )
109+ time .sleep (1.5 )
110+ with open (
111+ f"data/export-{ datetime .today ().date ()} .csv" , "w" , newline = ""
112+ ) as csvfile :
113+ writer = csv .writer (
114+ csvfile , delimiter = "," , quotechar = "|" , quoting = csv .QUOTE_MINIMAL
115+ )
116+ for entry in passwords :
117+ writer .writerow (entry )
118+ print ("Done!" )
46119
47120
48121def main () -> None :
49- global authenticated , auth_data , data , pool
50- args = parse_arguments ()
51- data .username = args .username
52- data .master_password = args .password
53- if args .password is not None and args .username is not None :
54- key = authenticate_user (get_connection (), data )
55- if key is not None :
56- auth_data .key = key
57- authenticated = True
58- elif args .username is not None and args .password is None :
59- data .master_password = input ("Enter Master Password: " )
60- key = authenticate_user (get_connection (), data )
61- if key is not None :
62- authenticated = True
63- auth_data .key = key
64-
65- auth_data .username = data .username
122+ global authenticated
66123 if authenticated :
67124 banner = r"""
68125__ __ _ ______ __
@@ -71,106 +128,99 @@ def main() -> None:
71128 \ V V / (_| | | | (_| | __/ | | | __/ | |
72129 \_/\_/ \__,_|_| \__,_|\___|_| |_|_| |_|
73130 -- created by supun
74-
75131type .help or ? for help and x or .exit to exit.
76132
77133 1.) Add a Entry [A]
78134 2.) Search Entry [S]
79135 3.) List Entries [L]
80136 4.) Delete Entry [D]
137+
138+ PRESS X TO QUITE
81139 """
82140 print (banner )
83141 main_logic ()
84142
85143
86144def main_logic ():
87145 global auth_data
88- print (auth_data .key )
89146 while True :
90- user_input = input ("> " )
91- if user_input .upper () == ".CLEAR" :
147+ user_input = Prompt .ask ("[bold green]> [/bold green]" ).upper ()
148+
149+ if user_input == ".CLEAR" :
92150 os .system ("clear" )
93- if user_input == "?" or user_input .upper () == ".HELP" :
151+
152+ if user_input in ("?" , ".HELP" ):
94153 print (help_msg )
95- if (
96- user_input == "1"
97- or user_input .upper () == "A"
98- or user_input .upper () == ".ADD"
99- ):
154+
155+ if user_input in ("1" , "A" , ".ADD" ):
100156 while True :
101157 site = input (".add website_url > " ).strip ()
102158 if not site :
103- print (colored_string ( " You Must Add a Website .^." , "RED" ) )
159+ print ("[bold red] You Must Add a Website .^.[/bold red]" )
104160 else :
105161 break
106162 site_pass = input (".add password (leave this blank for random password) > " )
107163 if not site_pass :
108164 site_pass = generate_password ()
109165 entry : Entry = Entry (site , site_pass )
110166 add_password (get_connection (), auth_data , entry )
111- if (
112- user_input == "2"
113- or user_input .upper () == "S"
114- or user_input .upper () == ".SEARCH"
115- ):
167+
168+ if user_input in ("2" , "S" , ".SEARCH" ):
116169 site = input (".search > " )
117170 a = get_password (get_connection (), auth_data , site )
118171 print (a )
119172
120- if (
121- user_input == "3"
122- or user_input .upper () == "L"
123- or user_input .upper () == ".LIST"
124- ):
173+ if user_input in ("3" , "L" , ".LIST" ):
125174 passwords = list_passwords (get_connection (), auth_data )
126175 if passwords is None :
127176 print (f"No passwords for user { auth_data .username } " )
128- print (passwords )
129- if user_input .upper () == "D" or user_input .upper () == ".DEL" :
177+ else :
178+ table = Table (title = "List of Passwords" )
179+ table .add_column ("Site/Url" , style = "blue" )
180+ table .add_column ("Password" , style = "red" )
181+ for item in passwords :
182+ table .add_row (item [0 ], item [1 ])
183+ console = Console ()
184+ console .print (table )
185+
186+ if user_input in ("D" , "4" , ".DEL" ):
130187 while True :
131188 site = input (".search entry > " ).strip ()
132189 if not site :
133- print (colored_string ( " You Must Add a Website .^." , "RED" ) )
190+ print ("[bold red] You Must Add a Website .^.[bold red]" )
134191 else :
135192 break
136193 list_of_entries = get_password (get_connection (), auth_data , site )
194+
137195 if list_of_entries is None :
138196 print (f"no entries have { site } " )
139197 if list_of_entries is not None :
140- print (list_of_entries )
141- id = input ("Give the id of the entry you want to delete > " )
142- id = str (id ).strip ()
143- delete_passwod (get_connection (), auth_data , id )
144- if user_input .upper () == "X" or user_input .upper () == ".EXIT" :
198+ table = Table (title = "List of Entries" )
199+ table .add_column ("id" , style = "bold blue" )
200+ table .add_column ("Site/Url" , style = "green" )
201+ table .add_column ("Password" , style = "red" )
202+ for item in list_of_entries :
203+ table .add_row (str (item [0 ]), item [1 ], item [2 ].decode ("utf-8" ))
204+ console = Console ()
205+ console .print (table )
206+ choices = [str (id [0 ]) for id in list_of_entries ]
207+ id = questionary .select (
208+ "Which entry do you want to delet?" ,
209+ choices = choices ,
210+ qmark = "> " ,
211+ pointer = ">" ,
212+ ).ask ()
213+ delete_the_entry = Prompt .ask (
214+ f"Are You sure You want to delete [bold red]{ id } [/bold red] { '[y/N]' } ?" ,
215+ default = False ,
216+ )
217+ if delete_the_entry :
218+ delete_passwod (get_connection (), auth_data , id )
219+
220+ if user_input in ("X" , ".EXIT" ):
145221 break
146222
147223
148- def parse_arguments () -> argparse .Namespace :
149- parser = argparse .ArgumentParser ()
150- subparser = parser .add_subparsers (
151- title = "Commands" ,
152- )
153- parser .add_argument ("-u" , "--username" , help = "use the username given here" )
154- parser .add_argument ("-p" , "--password" , help = "use the password given here" )
155- parser .add_argument ("-a" , "--add" , help = "add password" )
156-
157- init_parser = subparser .add_parser (
158- "init" , aliases = "i" , help = "Inizialize password repo"
159- )
160- init_parser .add_argument (
161- "username" , help = "username for initialize the password store"
162- )
163- init_parser .set_defaults (func = init_store )
164- subparser .add_parser ("new" , help = "Inizialize new password repo" ).set_defaults (
165- func = init_store
166- )
167-
168- args = parser .parse_args ()
169- if hasattr (args , "func" ):
170- args .func (args )
171- return args
172-
173-
174224help_msg = """
175225.help, ? Show this menu
176226.clear Clear the screen
@@ -183,4 +233,4 @@ def parse_arguments() -> argparse.Namespace:
183233
184234
185235if __name__ == "__main__" :
186- main ()
236+ app ()
0 commit comments