Mercurial > cgi-bin > hgweb.cgi > PassMan
comparison src/main/kotlin/name/blackcap/passman/UpdateSubcommand.kt @ 21:ea65ab890f66
More work to support interactive feature.
author | David Barts <n5jrn@me.com> |
---|---|
date | Tue, 02 Jul 2024 11:27:39 -0700 |
parents | 302d224bbd57 |
children |
comparison
equal
deleted
inserted
replaced
20:4391afcf6bd0 | 21:ea65ab890f66 |
---|---|
2 | 2 |
3 import org.apache.commons.cli.* | 3 import org.apache.commons.cli.* |
4 import java.sql.Types | 4 import java.sql.Types |
5 import java.util.* | 5 import java.util.* |
6 import kotlin.properties.Delegates | 6 import kotlin.properties.Delegates |
7 import kotlin.system.exitProcess | |
8 | 7 |
9 class UpdateSubcommand(): Subcommand() { | 8 class UpdateSubcommand(): Subcommand() { |
10 private lateinit var commandLine: CommandLine | 9 private lateinit var commandLine: CommandLine |
11 private lateinit var db: Database | 10 private lateinit var db: Database |
12 private lateinit var nameIn: String | 11 private lateinit var nameIn: String |
26 val SENSITIVE_FIELDS = setOf<String>("password") | 25 val SENSITIVE_FIELDS = setOf<String>("password") |
27 } | 26 } |
28 | 27 |
29 override fun run(args: Array<String>) { | 28 override fun run(args: Array<String>) { |
30 parseArguments(args) | 29 parseArguments(args) |
30 if (commandLine.hasOption(HELP)) { | |
31 return | |
32 } | |
31 checkDatabase() | 33 checkDatabase() |
32 try { | 34 try { |
33 update() | 35 update() |
34 } finally { | 36 } finally { |
35 cleanUp() | 37 cleanUp() |
45 addOption("v", VERBOSE, false, "Print the generated password.") | 47 addOption("v", VERBOSE, false, "Print the generated password.") |
46 } | 48 } |
47 try { | 49 try { |
48 commandLine = DefaultParser().parse(options, args) | 50 commandLine = DefaultParser().parse(options, args) |
49 } catch (e: ParseException) { | 51 } catch (e: ParseException) { |
50 die(e.message ?: "syntax error", 2) | 52 throw SubcommandException(message = e.message ?: "syntax error", status = 2, cause = e) |
51 } | 53 } |
52 if (commandLine.hasOption(HELP)) { | 54 if (commandLine.hasOption(HELP)) { |
53 HelpFormatter().printHelp("$SHORTNAME update [options] name", options) | 55 HelpFormatter().printHelp("$SHORTNAME update [options] name", options) |
54 exitProcess(0) | 56 return |
55 } | 57 } |
56 checkArguments() | 58 checkArguments() |
57 db = Database.open() | 59 db = Database.default |
58 nameIn = commandLine.args[0] | 60 nameIn = commandLine.args[0] |
59 id = db.makeKey(nameIn) | 61 id = db.makeKey(nameIn) |
60 val rawLength = commandLine.getOptionValue(LENGTH) | 62 val rawLength = commandLine.getOptionValue(LENGTH) |
61 length = try { | 63 length = try { |
62 rawLength?.toInt() ?: DEFAULT_GENERATED_LENGTH | 64 rawLength?.toInt() ?: DEFAULT_GENERATED_LENGTH |
63 } catch (e: NumberFormatException) { | 65 } catch (e: NumberFormatException) { |
64 -1 | 66 -1 |
65 } | 67 } |
66 if (length < MIN_GENERATED_LENGTH) { | 68 if (length < MIN_GENERATED_LENGTH) { |
67 die("${see(rawLength)} - invalid length") | 69 throw SubcommandException(message = "${see(rawLength)} - invalid length") |
68 } | 70 } |
69 } | 71 } |
70 | 72 |
71 private fun checkArguments(): Unit { | 73 private fun checkArguments(): Unit { |
72 var bad = false | 74 var bad = false |
77 bad = true | 79 bad = true |
78 } | 80 } |
79 } | 81 } |
80 } | 82 } |
81 if (bad) { | 83 if (bad) { |
82 exitProcess(2); | 84 throw SubcommandException(status = 2) |
83 } | 85 } |
84 if (commandLine.args.isEmpty()) { | 86 if (commandLine.args.isEmpty()) { |
85 die("expecting site name", 2) | 87 throw SubcommandException(message = "expecting site name", status = 2) |
86 } | 88 } |
87 if (commandLine.args.size > 1) { | 89 if (commandLine.args.size > 1) { |
88 die("unexpected trailing arguments", 2) | 90 throw SubcommandException(message = "unexpected trailing arguments", status = 2) |
89 } | 91 } |
90 } | 92 } |
91 | 93 |
92 private fun checkDatabase(): Unit { | 94 private fun checkDatabase(): Unit { |
93 db.connection.prepareStatement("select count(*) from passwords where id = ?").use { | 95 db.connection.prepareStatement("select count(*) from passwords where id = ?").use { |
94 it.setLong(1, id) | 96 it.setLong(1, id) |
95 val result = it.executeQuery() | 97 val result = it.executeQuery() |
96 result.next() | 98 result.next() |
97 val count = result.getInt(1) | 99 val count = result.getInt(1) |
98 if (count < 1) { | 100 if (count < 1) { |
99 die("no record matches " + see(nameIn)) | 101 throw SubcommandException(message = "no record matches " + see(nameIn)) |
100 } | 102 } |
101 } | 103 } |
102 } | 104 } |
103 | 105 |
104 private fun update(): Unit { | 106 private fun update(): Unit { |
138 } | 140 } |
139 } | 141 } |
140 } | 142 } |
141 | 143 |
142 private fun updateOne(name: String): Unit { | 144 private fun updateOne(name: String): Unit { |
143 val prompt = name.replaceFirstChar { it.titlecase(Locale.getDefault()) } + ": " | 145 val prompt = name.replaceFirstChar { it.uppercase(Locale.getDefault()) } + ": " |
144 val value: Any? = if (name in SENSITIVE_FIELDS) { | 146 val value: Any? = if (name in SENSITIVE_FIELDS) { |
145 updatePassword() | 147 try { |
148 getPassword(prompt) | |
149 } catch (e: ConsoleException) { | |
150 throw SubcommandException(message = e.message, cause = e) | |
151 } | |
146 } else { | 152 } else { |
147 val rawValue = readLine(prompt) | 153 val rawValue = readLine(prompt) |
148 if (name in NULLABLE_FIELDS && rawValue == NULL_SPECIFIED) { | 154 if (name in NULLABLE_FIELDS && rawValue == NULL_SPECIFIED) { |
149 null | 155 null |
150 } else { | 156 } else { |
179 printPassword(newPassword) | 185 printPassword(newPassword) |
180 } | 186 } |
181 addOne("password", newPassword) | 187 addOne("password", newPassword) |
182 } | 188 } |
183 | 189 |
184 private fun updatePassword(): CharArray { | |
185 while (true) { | |
186 val pw1 = getPassword("Password: ") | |
187 if (pw1.isEmpty()) { | |
188 return pw1 | |
189 } | |
190 val pw2 = getPassword("Verification: ") | |
191 if (pw1 contentEquals pw2) { | |
192 return pw1 | |
193 } | |
194 error("mismatch, try again") | |
195 } | |
196 } | |
197 } | 190 } |