/models/models.go

https://github.com/duo-labs/webauthn.io · Go · 89 lines · 66 code · 11 blank · 12 comment · 13 complexity · aab21370576094ab6c8c439d7bdf5a6a MD5 · raw file

  1. package models
  2. import (
  3. "crypto/rand"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "os"
  9. "time"
  10. "github.com/duo-labs/webauthn.io/config"
  11. log "github.com/duo-labs/webauthn.io/logger"
  12. _ "github.com/go-sql-driver/mysql" // Blank import needed to import mysql
  13. "github.com/jinzhu/gorm"
  14. _ "github.com/mattn/go-sqlite3" // Blank import needed to import sqlite3
  15. )
  16. var db *gorm.DB
  17. var err error
  18. // ErrUsernameTaken is thrown when a user attempts to register a username that is taken.
  19. var ErrUsernameTaken = errors.New("username already taken")
  20. // Copy of auth.GenerateSecureKey to prevent cyclic import with auth library
  21. func generateSecureKey() string {
  22. k := make([]byte, 32)
  23. io.ReadFull(rand.Reader, k)
  24. return fmt.Sprintf("%x", k)
  25. }
  26. // BytesToID converts a byte slice to a uint. This is needed because the
  27. // WebAuthn specification deals with byte buffers, while the primary keys in
  28. // our database are uints.
  29. func BytesToID(buf []byte) uint {
  30. // TODO: Probably want to catch the number of bytes converted in production
  31. id, _ := binary.Uvarint(buf)
  32. return uint(id)
  33. }
  34. // Setup initializes the Conn object
  35. // It also populates the Config object
  36. func Setup(config *config.Config) error {
  37. createDb := false
  38. if _, err = os.Stat(config.DBPath); err != nil || config.DBPath == ":memory:" {
  39. createDb = true
  40. }
  41. // Open our database connection
  42. db, err = gorm.Open(config.DBName, config.DBPath)
  43. if err != nil {
  44. return err
  45. }
  46. db.LogMode(false)
  47. db.SetLogger(log.Logger)
  48. db.DB().SetMaxOpenConns(1)
  49. if err != nil {
  50. return err
  51. }
  52. // Migrate up to the latest version
  53. //If the database didn't exist, we need to create the admin user
  54. err := db.AutoMigrate(
  55. &User{},
  56. &Credential{},
  57. &Authenticator{},
  58. ).Error
  59. if err != nil {
  60. return err
  61. }
  62. gorm.NowFunc = func() time.Time {
  63. return time.Now().UTC()
  64. }
  65. if createDb {
  66. // Create the default user
  67. initUser := User{
  68. Username: "admin",
  69. DisplayName: "Example Admin",
  70. }
  71. err = db.Save(&initUser).Error
  72. if err != nil {
  73. log.Infof("error creating initial user: %s", err)
  74. return err
  75. }
  76. }
  77. return nil
  78. }