Skip to content

Commit

Permalink
refactor into subpackages
Browse files Browse the repository at this point in the history
  • Loading branch information
daveio committed Mar 5, 2019
1 parent 2ba9be7 commit 8f2a2d0
Show file tree
Hide file tree
Showing 14 changed files with 223 additions and 136 deletions.
7 changes: 5 additions & 2 deletions .idea/markdown-navigator.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -4,7 +4,7 @@

Generate OATH-TOTP one-time passwords from the command line.

See also [`zsh-gotp`][link-zsh-gotp] for easy installation and integration with `zsh`.
See also [`zsh-gotp`][link-zsh-gotp] for easy installation and integration with `zsh`.

### NOT YET FUNCTIONAL OR READY FOR USE!

Expand Down
9 changes: 0 additions & 9 deletions cmd_delete.go

This file was deleted.

20 changes: 0 additions & 20 deletions cmd_generate.go

This file was deleted.

9 changes: 0 additions & 9 deletions cmd_store.go

This file was deleted.

29 changes: 29 additions & 0 deletions commands/commands.go
@@ -0,0 +1,29 @@
package commands

import (
"fmt"
"github.com/daveio/gotp/otputils"
"github.com/daveio/gotp/storage"
)

func Generate(keychain storage.Keychain, site string, uid string) {
secretKey, err := storage.GetSecret(keychain, site, uid)
if err == nil {
if uid == "__default" {
fmt.Printf("%s : ", site)
} else {
fmt.Printf("%s @ %s : ", uid, site)
}
fmt.Printf("%s\n", otputils.GenerateOTP(secretKey))
} else {
fmt.Printf("%s", err)
}
}

func Store(keychain storage.Keychain, site string, key string, uid string) {
storage.StoreSecret(keychain, site, key, uid)
}

func Delete(keychain storage.Keychain, site string, uid string) {
_ = keychain
}
11 changes: 11 additions & 0 deletions errors/errors.go
@@ -0,0 +1,11 @@
package errors

import "fmt"

func (e *UidError) Error() string {
return fmt.Sprintf("UID %s not found for site %s", e.Site, e.Uid)
}

func (e *SiteError) Error() string {
return fmt.Sprintf("Site %s not found", e.Site)
}
10 changes: 10 additions & 0 deletions errors/types.go
@@ -0,0 +1,10 @@
package errors

type SiteError struct {
Site string
}

type UidError struct {
Site string
Uid string
}
144 changes: 72 additions & 72 deletions main.go
Expand Up @@ -2,115 +2,115 @@ package main

import (
"fmt"
"github.com/tucnak/store"
"github.com/daveio/gotp/commands"
"github.com/daveio/gotp/storage"
"github.com/daveio/gotp/verbose"
"gopkg.in/alecthomas/kingpin.v2"
"os"
)

var (
V = verbose.V
appVersion = fmt.Sprintf("%d.%d.%d", AppVersionMajor, AppVersionMinor, AppVersionPatch)
appVersionWithDate = fmt.Sprintf("%s %d", appVersion, AppVersionDate)
app = kingpin.
New("gotp", "Generate OATH-TOTP one-time passwords from the command line.")
debug = app.
Flag("debug", "Enable debug mode.").
Short('d').
mVerbose = app.
Flag("verbose", "Show more detail.").
Short('v').
Bool()
storeCommand = app.
Command("store", "Store a new account.").
Alias("s")
Command("store", "Store a new account.").
Alias("s")
storeSite = storeCommand.
Arg("site", "An identifier for the site which you will use to generate OTPs.").
Required().
String()
Arg("site", "An identifier for the site which you will use to generate OTPs.").
Required().
String()
storeKey = storeCommand.
Arg("key", "Your secret key for the site.").
Required().
String()
Arg("key", "Your secret key for the site.").
Required().
String()
storeUid = storeCommand.
Flag("uid", "An optional username or other identifier for the account this key is for. Useful if you have multiple accounts on a single site.").
Short('u').
String()
Flag("uid", "An optional username or other identifier for the account this key is for. Useful if you have multiple accounts on a single site.").
Short('u').
String()
/*
storeURICommand = app.
Command("store-uri", "Store a new account using a totp:// URI.").
Alias("su")
storeURIURI = storeURICommand.
Arg("uri", "A valid totp:// URI").
Required().
String()
*/
generateCommand = app.
Command("generate", "Generate OTP(s) for a site.").
Alias("g")
Command("generate", "Generate OTP(s) for a site.").
Alias("g")
generateSite = generateCommand.
Arg("site", "The site to generate OTP(s) for.").
Required().
String()
Arg("site", "The site to generate OTP(s) for.").
Required().
String()
generateUid = generateCommand.
Flag("uid", "An optional identifier for the key to use. Only necessary if you have multiple keys for a site.").
Short('u').
String()
Flag("uid", "An optional identifier for the key to use. Only necessary if you have multiple keys for a site.").
Short('u').
String()
deleteCommand = app.
Command("delete", "Generate OTP(s) for a site.").
Alias("d")
Command("delete", "Generate OTP(s) for a site.").
Alias("d")
deleteSite = deleteCommand.
Arg("site", "The site to delete.").
Required().
String()
Arg("site", "The site to delete.").
Required().
String()
deleteUid = deleteCommand.
Flag("uid", "An optional identifier for the key to delete. Only necessary if you have multiple keys for a site.").
Short('u').
String()
Flag("uid", "An optional identifier for the key to delete. Only necessary if you have multiple keys for a site.").
Short('u').
String()
)

type Site struct {
UIDs map[string]string `json:"uids"`
}

type Keychain struct {
Sites map[string]Site `json:"sites"`
}

func init() {
store.Init("gotp")
}

func loadConfig() Keychain {
var keychain Keychain
err := store.Load("keychain.json", &keychain)
if err != nil {
panic(err)
}
return keychain
}

func saveConfig(keychain *Keychain) {
err := store.Save("keychain.json", &keychain)
if err != nil {
panic(err)
}
storage.InitStorage("gotp")
}

func main() {
keychain := loadConfig()
app.Version(appVersionWithDate)
appCmd, appErr := app.Parse(os.Args[1:])
verbose.InitV(*mVerbose, appVersion)
V("Verbose mode enabled")
keychain := storage.LoadConfig()
if len(keychain.Sites) < 1 {
keychain.Sites = make(map[string]Site)
}
if *debug {
fmt.Println("Debug mode enabled.")
keychain.Sites = make(map[string]storage.Site)
}
appVersion := fmt.Sprintf("%d.%d.%d (%d)", AppVersionMajor, AppVersionMinor,
AppVersionPatch, AppVersionDate)
app.Version(appVersion)
switch kingpin.MustParse(app.Parse(os.Args[1:])) {
switch kingpin.MustParse(appCmd, appErr) {
case storeCommand.FullCommand():
V("storing a new item")
if *storeUid != "" {
cmdStoreWithUID(keychain, *storeSite, *storeKey, *storeUid)
commands.Store(keychain, *storeSite, *storeKey, *storeUid)
} else {
cmdStore(keychain, *storeSite, *storeKey)
commands.Store(keychain, *storeSite, *storeKey, "__default")
}
case generateCommand.FullCommand():
V("generating an OTP")
if *generateUid != "" {
cmdGenerateWithUID(keychain, *generateSite, *generateUid)
commands.Generate(keychain, *generateSite, *generateUid)
} else {
cmdGenerate(keychain, *generateSite)
commands.Generate(keychain, *generateSite, "__default")
}
case deleteCommand.FullCommand():
V("deleting an item")
if *deleteUid != "" {
cmdDeleteWithUID(keychain, *deleteSite, *deleteUid)
commands.Delete(keychain, *deleteSite, *deleteUid)
} else {
cmdDelete(keychain, *deleteSite)
commands.Delete(keychain, *deleteSite, "__default")
}
/* case storeURICommand.FullCommand():
site, uid, key, err := parseURI(*storeURIURI)
if err == nil {
V(fmt.Sprintf("site: %s, uid: %s, key: %s", site, uid, key))
} else {
fmt.Println("Malformed URI")
} */
default:
V("BUG: invalid command uncaught by CLI parser")
}
saveConfig(&keychain)
storage.SaveConfig(&keychain)
}
13 changes: 11 additions & 2 deletions totp.go → otputils/otputils.go
@@ -1,15 +1,24 @@
package main
package otputils

import (
"fmt"
"github.com/pquerna/otp/totp"
"regexp"
"time"
)

func generateOTP(key string) string {
func GenerateOTP(key string) string {
res, _ := totp.GenerateCode(key, time.Now())
return res
}

func ParseURI(totpURI string) (site string, uid string, key string, errOut error) {
meta := regexp.QuoteMeta("?")
expr, _ := regexp.Compile("^otpauth://totp/(.*):(.*)" + meta + "(.*)$")
fmt.Println(expr.FindStringSubmatch(totpURI))
return "site", "uid", "key", nil
}

/*
func totpDisplay(key *otp.Key, data []byte) {
fmt.Printf("Issuer: %s\n", key.Issuer())
Expand Down
21 changes: 0 additions & 21 deletions storage.go

This file was deleted.

0 comments on commit 8f2a2d0

Please sign in to comment.