Go Back

0 package gmi

1

2 import (

3 "gemigit/auth"

4 "gemigit/config"

5 "gemigit/db"

6 "gemigit/csrf"

7

8 "github.com/pitr/gig"

9 "github.com/pquerna/otp/totp"

10

11 "log"

12 "bytes"

13 "image/png"

14 )

15

16 var keys = make(map[string]string)

17

18 func otpRedirect(c gig.Context) error {

19 return c.NoContent(gig.StatusRedirectTemporary,

20 "/account/" + csrf.Token(c.CertHash() + "/otp"))

21 }

22

23 func CreateTOTP(c gig.Context) error {

24

25 user, exist := db.GetUser(c.CertHash())

26 if !exist {

27 return c.NoContent(gig.StatusBadRequest, "Invalid username")

28 }

29

30 key, err := totp.Generate(totp.GenerateOpts{

31 Issuer: config.Cfg.Title,

32 AccountName: user.Name,

33 })

34

35 if err != nil {

36 log.Println(err)

37 return c.NoContent(gig.StatusBadRequest, "Unexpected error")

38 }

39

40 var buf bytes.Buffer

41 img, err_ := key.Image(200, 200)

42 if err_ != nil {

43 log.Println(err)

44 return c.NoContent(gig.StatusBadRequest, "Unexpected error")

45 }

46 png.Encode(&buf, img)

47

48 keys[c.CertHash()] = key.Secret()

49

50 return c.Blob("image/png", buf.Bytes())

51 }

52

53 func ConfirmTOTP(c gig.Context) error {

54

55 user, exist := db.GetUser(c.CertHash())

56 if !exist {

57 return c.NoContent(gig.StatusBadRequest, "Invalid username")

58 }

59

60 query, err := c.QueryString()

61 if err != nil {

62 log.Println(err)

63 return c.NoContent(gig.StatusBadRequest, "Unexpected error")

64 }

65 if query == "" {

66 return c.NoContent(gig.StatusInput, "Code")

67 }

68

69 key, exist := keys[c.CertHash()]

70

71 valid := false

72 if exist {

73 valid = totp.Validate(query, key)

74 }

75 if !valid {

76 return c.NoContent(gig.StatusBadRequest, "Invalid code")

77 }

78

79 err = user.SetSecret(key)

80 if err != nil {

81 log.Println(err)

82 return c.NoContent(gig.StatusBadRequest, "Unexpected error")

83 }

84

85 return otpRedirect(c)

86 }

87

88 func LoginOTP(c gig.Context) error {

89

90 query, err := c.QueryString()

91 if err != nil {

92 log.Println(err)

93 return c.NoContent(gig.StatusBadRequest, "Unexpected error")

94 }

95 if query == "" {

96 return c.NoContent(gig.StatusInput, "Code")

97 }

98

99 err = auth.LoginOTP(c.CertHash(), query)

100 if err != nil && err.Error() == "wrong code" {

101 return c.NoContent(gig.StatusInput, "Code")

102 }

103 if err != nil {

104 return c.NoContent(gig.StatusBadRequest, err.Error())

105 }

106

107 return otpRedirect(c)

108 }

109

110 func RemoveTOTP(c gig.Context) error {

111

112 user, exist := db.GetUser(c.CertHash())

113 if !exist {

114 return c.NoContent(gig.StatusBadRequest, "Invalid username")

115 }

116

117 query, err := c.QueryString()

118 if err != nil {

119 log.Println(err)

120 return c.NoContent(gig.StatusBadRequest, "Unexpected error")

121 }

122 if query == "" {

123 return c.NoContent(gig.StatusInput, "Code")

124 }

125

126 valid := totp.Validate(query, user.Secret)

127 if !valid {

128 return c.NoContent(gig.StatusInput, "Code")

129 }

130

131 err = user.SetSecret("")

132 if err != nil {

133 log.Println(err)

134 return c.NoContent(gig.StatusBadRequest, "Unexpected error")

135 }

136

137 return otpRedirect(c)

138 }

139

140 func ShowOTP(c gig.Context) error {

141 user, exist := db.GetUser(c.CertHash())

142 if !exist {

143 return c.NoContent(gig.StatusBadRequest, "Invalid username")

144 }

145 data := struct {

146 Secret bool

147 }{

148 Secret: user.Secret != "",

149 }

150 return execT(c, "otp.gmi", data)

151 }

152