totp codes don't seem to sync but they're here!!

This commit is contained in:
ari melody 2025-01-20 23:49:54 +00:00
parent 5e493554dc
commit ae254dd731
Signed by: ari
GPG key ID: CF99829C92678188
7 changed files with 345 additions and 27 deletions

144
main.go
View file

@ -14,6 +14,7 @@ import (
"arimelody-web/api"
"arimelody-web/controller"
"arimelody-web/global"
"arimelody-web/model"
"arimelody-web/templates"
"arimelody-web/view"
@ -30,10 +31,6 @@ func main() {
fmt.Printf("made with <3 by ari melody\n\n")
// initialise database connection
if env := os.Getenv("ARIMELODY_DB_HOST"); env != "" { global.Config.DB.Host = env }
if env := os.Getenv("ARIMELODY_DB_NAME"); env != "" { global.Config.DB.Name = env }
if env := os.Getenv("ARIMELODY_DB_USER"); env != "" { global.Config.DB.User = env }
if env := os.Getenv("ARIMELODY_DB_PASS"); env != "" { global.Config.DB.Pass = env }
if global.Config.DB.Host == "" {
fmt.Fprintf(os.Stderr, "FATAL: db.host not provided! Exiting...\n")
os.Exit(1)
@ -76,6 +73,136 @@ func main() {
arg := os.Args[1]
switch arg {
case "createTOTP":
if len(os.Args) < 4 {
fmt.Fprintf(os.Stderr, "FATAL: `username` and `name` must be specified for createTOTP.\n")
os.Exit(1)
}
username := os.Args[2]
totpName := os.Args[3]
secret := controller.GenerateAlnumString(32)
account, err := controller.GetAccount(global.DB, username)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fetch account \"%s\": %v\n", username, err)
os.Exit(1)
}
if account == nil {
fmt.Fprintf(os.Stderr, "Account \"%s\" does not exist.\n", username)
os.Exit(1)
}
totp := model.TOTP {
AccountID: account.ID,
Name: totpName,
Secret: string(secret),
}
err = controller.CreateTOTP(global.DB, &totp)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create TOTP method: %v\n", err)
os.Exit(1)
}
url := controller.GenerateTOTPURI(account.Username, totp.Secret)
fmt.Printf("%s\n", url)
return
case "deleteTOTP":
if len(os.Args) < 4 {
fmt.Fprintf(os.Stderr, "FATAL: `username` and `name` must be specified for deleteTOTP.\n")
os.Exit(1)
}
username := os.Args[2]
totpName := os.Args[3]
account, err := controller.GetAccount(global.DB, username)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fetch account \"%s\": %v\n", username, err)
os.Exit(1)
}
if account == nil {
fmt.Fprintf(os.Stderr, "Account \"%s\" does not exist.\n", username)
os.Exit(1)
}
err = controller.DeleteTOTP(global.DB, account.ID, totpName)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create TOTP method: %v\n", err)
os.Exit(1)
}
fmt.Printf("TOTP method \"%s\" deleted.\n", totpName)
return
case "listTOTP":
if len(os.Args) < 3 {
fmt.Fprintf(os.Stderr, "FATAL: `username` must be specified for listTOTP.\n")
os.Exit(1)
}
username := os.Args[2]
account, err := controller.GetAccount(global.DB, username)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fetch account \"%s\": %v\n", username, err)
os.Exit(1)
}
if account == nil {
fmt.Fprintf(os.Stderr, "Account \"%s\" does not exist.\n", username)
os.Exit(1)
}
totps, err := controller.GetTOTPsForAccount(global.DB, account.ID)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create TOTP methods: %v\n", err)
os.Exit(1)
}
for i, totp := range totps {
fmt.Printf("%d. %s - Created %s\n", i + 1, totp.Name, totp.CreatedAt)
}
if len(totps) == 0 {
fmt.Printf("\"%s\" has no TOTP methods.\n", account.Username)
}
return
case "testTOTP":
if len(os.Args) < 4 {
fmt.Fprintf(os.Stderr, "FATAL: `username` and `name` must be specified for testTOTP.\n")
os.Exit(1)
}
username := os.Args[2]
totpName := os.Args[3]
account, err := controller.GetAccount(global.DB, username)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fetch account \"%s\": %v\n", username, err)
os.Exit(1)
}
if account == nil {
fmt.Fprintf(os.Stderr, "Account \"%s\" does not exist.\n", username)
os.Exit(1)
}
totp, err := controller.GetTOTP(global.DB, account.ID, totpName)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fetch TOTP method \"%s\": %v\n", totpName, err)
os.Exit(1)
}
if totp == nil {
fmt.Fprintf(os.Stderr, "TOTP method \"%s\" does not exist for account \"%s\"\n", totpName, username)
os.Exit(1)
}
code := controller.GenerateTOTP(totp.Secret, 0)
fmt.Printf("%s\n", code)
return
case "createInvite":
fmt.Printf("Creating invite...\n")
invite, err := controller.CreateInvite(global.DB, 16, time.Hour * 24)
@ -120,8 +247,8 @@ func main() {
return
case "deleteAccount":
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "FATAL: Account name not specified for -deleteAccount\n")
if len(os.Args) < 3 {
fmt.Fprintf(os.Stderr, "FATAL: `username` must be specified for deleteAccount\n")
os.Exit(1)
}
username := os.Args[2]
@ -159,6 +286,11 @@ func main() {
// command help
fmt.Print(
"Available commands:\n\n" +
"createTOTP <username> <name>:\n\tCreates a timed one-time passcode method.\n" +
"listTOTP <username>:\n\tLists an account's TOTP methods.\n" +
"deleteTOTP <username> <name>:\n\tDeletes an account's TOTP method.\n" +
"testTOTP <username> <name>:\n\tGenerates the code for an account's TOTP method.\n" +
"\n" +
"createInvite:\n\tCreates an invite code to register new accounts.\n" +
"purgeInvites:\n\tDeletes all available invite codes.\n" +
"listAccounts:\n\tLists all active accounts.\n",