Skip to content
This repository was archived by the owner on Sep 9, 2022. It is now read-only.

Commit f7dd30a

Browse files
committed
build secman insert command pipe in pkg/pipe/insert pkg
1 parent c4668a3 commit f7dd30a

File tree

1 file changed

+387
-0
lines changed

1 file changed

+387
-0
lines changed

pkg/pipe/insert/insert.go

+387
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,387 @@
1+
package insert
2+
3+
import (
4+
"os"
5+
"fmt"
6+
"log"
7+
"strings"
8+
9+
"github.com/abdfnx/gosh"
10+
"github.com/charmbracelet/lipgloss"
11+
"github.com/scmn-dev/secman/constants"
12+
"github.com/scmn-dev/secman/pkg/options"
13+
tea "github.com/charmbracelet/bubbletea"
14+
"github.com/charmbracelet/bubbles/spinner"
15+
"github.com/charmbracelet/bubbles/textinput"
16+
"github.com/scmn-dev/secman/internal/shared"
17+
)
18+
19+
const okButton shared.Index = iota
20+
21+
type model struct {
22+
styles shared.Styles
23+
focusIndex int
24+
index shared.Index
25+
inputs []textinput.Model
26+
spinner spinner.Model
27+
state shared.State
28+
pwType string
29+
message string
30+
}
31+
32+
func Insert(o *options.PasswordsOptions) model {
33+
st := shared.DefaultStyles()
34+
35+
var inps = func() int {
36+
if o.Logins {
37+
return 5
38+
} else if o.CreditCards {
39+
return 6
40+
} else if o.Emails {
41+
return 3
42+
} else if o.Notes {
43+
return 2
44+
} else if o.Servers {
45+
return 10
46+
}
47+
48+
return 0
49+
}
50+
51+
m := model{
52+
styles: st,
53+
inputs: make([]textinput.Model, inps()),
54+
spinner: shared.NewSpinner(),
55+
state: shared.Ready,
56+
pwType: shared.PasswordType(o),
57+
}
58+
59+
var t textinput.Model
60+
for i := range m.inputs {
61+
t = textinput.New()
62+
t.CursorStyle = st.Cursor
63+
t.Prompt = st.FocusedPrompt.String()
64+
t.CharLimit = 32
65+
66+
if o.Logins {
67+
switch i {
68+
case 0:
69+
t.Focus()
70+
t.Placeholder = "Title"
71+
t.CharLimit = 50
72+
73+
case 1:
74+
t.Placeholder = "URL"
75+
t.CharLimit = 50
76+
77+
case 2:
78+
t.Placeholder = "Username"
79+
t.CharLimit = 50
80+
81+
case 3:
82+
t.Placeholder = "Password"
83+
t.EchoMode = textinput.EchoPassword
84+
t.EchoCharacter = '•'
85+
86+
case 4:
87+
t.Placeholder = "Extra"
88+
t.CharLimit = 50
89+
}
90+
} else if o.CreditCards {
91+
switch i {
92+
case 0:
93+
t.Focus()
94+
t.Placeholder = "Title"
95+
t.CharLimit = 50
96+
97+
case 1:
98+
t.Placeholder = "Card Holder"
99+
t.CharLimit = 50
100+
101+
case 2:
102+
t.Placeholder = "Card Type"
103+
t.CharLimit = 50
104+
105+
case 3:
106+
t.Placeholder = "Card Number"
107+
t.CharLimit = 16
108+
109+
case 4:
110+
t.Placeholder = "Expiry Date"
111+
t.CharLimit = 5
112+
113+
case 5:
114+
t.Placeholder = "Verification Number"
115+
t.CharLimit = 3
116+
}
117+
} else if o.Emails {
118+
switch i {
119+
case 0:
120+
t.Focus()
121+
t.Placeholder = "Title"
122+
t.CharLimit = 50
123+
124+
case 1:
125+
t.Placeholder = "Email"
126+
t.CharLimit = 50
127+
128+
case 2:
129+
t.Placeholder = "Password"
130+
t.EchoMode = textinput.EchoPassword
131+
t.EchoCharacter = '•'
132+
}
133+
} else if o.Notes {
134+
switch i {
135+
case 0:
136+
t.Focus()
137+
t.Placeholder = "Title"
138+
t.CharLimit = 50
139+
140+
case 1:
141+
t.Placeholder = "Note"
142+
t.CharLimit = 50
143+
}
144+
} else if o.Servers {
145+
switch i {
146+
case 0:
147+
t.Focus()
148+
t.Placeholder = "Title"
149+
t.CharLimit = 50
150+
151+
case 1:
152+
t.Placeholder = "Ip Address"
153+
t.CharLimit = 50
154+
155+
case 2:
156+
t.Placeholder = "Username"
157+
t.CharLimit = 50
158+
159+
case 3:
160+
t.Placeholder = "Password"
161+
t.EchoMode = textinput.EchoPassword
162+
t.EchoCharacter = '•'
163+
164+
case 4:
165+
t.Placeholder = "URL"
166+
t.CharLimit = 50
167+
168+
case 5:
169+
t.Placeholder = "Hosting Username"
170+
t.CharLimit = 50
171+
172+
case 6:
173+
t.Placeholder = "Hosting Password"
174+
t.EchoMode = textinput.EchoPassword
175+
t.EchoCharacter = '•'
176+
177+
case 7:
178+
t.Placeholder = "Admin Username"
179+
t.CharLimit = 50
180+
181+
case 8:
182+
t.Placeholder = "Admin Password"
183+
t.EchoMode = textinput.EchoPassword
184+
t.EchoCharacter = '•'
185+
186+
case 9:
187+
t.Placeholder = "Extra"
188+
t.CharLimit = 50
189+
}
190+
}
191+
192+
m.inputs[i] = t
193+
}
194+
195+
return m
196+
}
197+
198+
func (m model) Init() tea.Cmd {
199+
return textinput.Blink
200+
}
201+
202+
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
203+
cmd := m.updateInputs(msg)
204+
205+
switch msg := msg.(type) {
206+
case tea.KeyMsg:
207+
switch msg.Type {
208+
case tea.KeyCtrlC:
209+
return m, tea.Quit
210+
211+
default:
212+
if m.state == shared.Loading {
213+
return m, nil
214+
}
215+
216+
switch msg.String() {
217+
case "tab", "shift+tab", "enter", "up", "down":
218+
s := msg.String()
219+
220+
if s == "enter" {
221+
if m.index == okButton {
222+
m.state = shared.Loading
223+
m.message = ""
224+
225+
return m, tea.Batch(
226+
smi(m),
227+
spinner.Tick,
228+
)
229+
} else {
230+
return m, tea.Quit
231+
}
232+
}
233+
234+
if s == "up" || s == "shift+tab" {
235+
m.focusIndex--
236+
} else {
237+
m.focusIndex++
238+
}
239+
240+
if m.focusIndex > len(m.inputs) {
241+
m.focusIndex = 0
242+
} else if m.focusIndex < 0 {
243+
m.focusIndex = len(m.inputs)
244+
}
245+
246+
cmds := make([]tea.Cmd, len(m.inputs))
247+
248+
for i := 0; i <= len(m.inputs)-1; i++ {
249+
if i == m.focusIndex {
250+
cmds[i] = m.inputs[i].Focus()
251+
continue
252+
}
253+
254+
m.inputs[i].Blur()
255+
}
256+
257+
return m, tea.Batch(cmds...)
258+
}
259+
260+
return m, nil
261+
}
262+
263+
case shared.SuccessMsg:
264+
m.state = shared.Ready
265+
m.message = m.styles.Success.Render("🔑 Password created successfully!")
266+
267+
return m, nil
268+
269+
case shared.OtherMsg:
270+
m.state = shared.Ready
271+
head := m.styles.Error.Render("Your Authentication is Expired.")
272+
body := m.styles.Subtle.Render(" Refresh your authentication via `secman auth refresh`.\n")
273+
m.message = m.styles.Wrap.Render(head + body)
274+
275+
return m, nil
276+
277+
case shared.ErrorMsg:
278+
m.state = shared.Ready
279+
m.message = m.styles.Error.Render("An error occurred while creating your password. Please try again.")
280+
281+
return m, nil
282+
283+
case shared.Message:
284+
m.state = shared.Ready
285+
head := m.styles.Error.Render("Oh, what? There was a curious error we were not expecting.\n")
286+
body := m.styles.Subtle.Render(msg.Error())
287+
m.message = m.styles.Wrap.Render(head + body)
288+
289+
return m, nil
290+
291+
case spinner.TickMsg:
292+
var cmd tea.Cmd
293+
m.spinner, cmd = m.spinner.Update(msg)
294+
295+
return m, cmd
296+
}
297+
298+
return m, cmd
299+
}
300+
301+
func (m *model) updateInputs(msg tea.Msg) tea.Cmd {
302+
var cmds = make([]tea.Cmd, len(m.inputs))
303+
304+
for i := range m.inputs {
305+
m.inputs[i], cmds[i] = m.inputs[i].Update(msg)
306+
}
307+
308+
return tea.Batch(cmds...)
309+
}
310+
311+
func (m model) View() string {
312+
s := "\n\nCreate a new password for your account.\n\n"
313+
314+
if m.state == shared.Loading {
315+
s += spinnerView(m)
316+
} else {
317+
for i := range m.inputs {
318+
s += m.inputs[i].View() + "\n"
319+
}
320+
321+
s += "\n" + shared.OKButton(m.focusIndex == len(m.inputs), true, "Ok")
322+
323+
if m.message != "" {
324+
fmt.Println(lipgloss.NewStyle().Padding(0, 2).SetString(m.message).String())
325+
os.Exit(0)
326+
}
327+
}
328+
329+
return lipgloss.NewStyle().Padding(0, 2).SetString(constants.Logo("Secman Password Creator") + s).String()
330+
}
331+
332+
func spinnerView(m model) string {
333+
return m.spinner.View() + "🔑 Creating..."
334+
}
335+
336+
func smi(m model) tea.Cmd {
337+
return func() tea.Msg {
338+
insCmd := "sc insert "
339+
cmd := ""
340+
extra := "no-extra"
341+
342+
if m.pwType == "-l" {
343+
if m.inputs[4].Value() != "" {
344+
extra = m.inputs[4].Value()
345+
}
346+
} else if m.pwType == "-s" {
347+
if m.inputs[9].Value() != "" {
348+
extra = m.inputs[9].Value()
349+
}
350+
}
351+
352+
var CMD = func() string {
353+
if m.pwType == "-l" {
354+
cmd = insCmd + m.pwType + " -t " + fmt.Sprintf("\"%s\"", m.inputs[0].Value()) + " -u " + fmt.Sprintf("\"%s\"", m.inputs[1].Value()) + " -U " + fmt.Sprintf("\"%s\"", m.inputs[2].Value()) + " -p " + fmt.Sprintf("\"%s\"", m.inputs[3].Value()) + " -x " + extra
355+
} else if m.pwType == "-c" {
356+
cmd = insCmd + m.pwType + " -t " + fmt.Sprintf("\"%s\"", m.inputs[0].Value()) + " -C " + fmt.Sprintf("\"%s\"", m.inputs[1].Value()) + " -T " + fmt.Sprintf("\"%s\"", m.inputs[2].Value()) + " -N " + fmt.Sprintf("\"%s\"", m.inputs[3].Value()) + " -E " + fmt.Sprintf("\"%s\"", m.inputs[4].Value()) + " -V " + fmt.Sprintf("\"%s\"", m.inputs[5].Value())
357+
} else if m.pwType == "-e" {
358+
cmd = insCmd + m.pwType + " -t " + fmt.Sprintf("\"%s\"", m.inputs[0].Value()) + " -m " + fmt.Sprintf("\"%s\"", m.inputs[1].Value()) + " -p " + fmt.Sprintf("\"%s\"", m.inputs[2].Value())
359+
} else if m.pwType == "-n" {
360+
cmd = insCmd + m.pwType + " -t " + fmt.Sprintf("\"%s\"", m.inputs[0].Value()) + " -N " + fmt.Sprintf("\"%s\"", m.inputs[1].Value())
361+
} else if m.pwType == "-s" {
362+
cmd = insCmd + m.pwType + " -t " + fmt.Sprintf("\"%s\"", m.inputs[0].Value()) + " -i " + fmt.Sprintf("\"%s\"", m.inputs[1].Value()) + " -U " + fmt.Sprintf("\"%s\"", m.inputs[2].Value()) + " -p " + fmt.Sprintf("\"%s\"", m.inputs[3].Value()) + " -u " + fmt.Sprintf("\"%s\"", m.inputs[4].Value()) + " -H " + fmt.Sprintf("\"%s\"", m.inputs[5].Value()) + " -O " + fmt.Sprintf("\"%s\"", m.inputs[6].Value()) + " -a " + fmt.Sprintf("\"%s\"", m.inputs[7].Value()) + " -w " + fmt.Sprintf("\"%s\"", m.inputs[8].Value()) + " -x " + fmt.Sprintf("\"%s\"", m.inputs[9].Value())
363+
}
364+
365+
return cmd
366+
}
367+
368+
err, out, errout := gosh.RunOutput(CMD())
369+
370+
if err != nil {
371+
log.Printf("error: %v\n", err)
372+
fmt.Print(errout)
373+
}
374+
375+
out = strings.TrimSuffix(out, "\n")
376+
377+
if strings.Contains(out, "401") {
378+
return shared.OtherMsg{}
379+
} else if strings.Contains(out, "404") {
380+
return shared.ErrorMsg{}
381+
} else if strings.Contains(out, "200") {
382+
return shared.SuccessMsg{}
383+
}
384+
385+
return shared.SetMsg(out)
386+
}
387+
}

0 commit comments

Comments
 (0)