some 2fa, split main into multiple files
This commit is contained in:
parent
266e16a060
commit
f3cc9cdeed
|
@ -0,0 +1,44 @@
|
||||||
|
package scsusers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func generate2fa() string {
|
||||||
|
num, err := rand.Int(rand.Reader, big.NewInt(999999))
|
||||||
|
if err != nil {
|
||||||
|
return "918273"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%06d", num)
|
||||||
|
|
||||||
|
}
|
||||||
|
func Validate2FA(u *UserData, challenge string) bool {
|
||||||
|
v, ok := u.Get("2fa")
|
||||||
|
return ok && v == challenge
|
||||||
|
}
|
||||||
|
|
||||||
|
func Send2FA(u *UserData) error {
|
||||||
|
code := generate2fa()
|
||||||
|
u.Set("2fa", code)
|
||||||
|
u.Set("2faexpires", fmt.Sprintf("%d", time.Now().Add(15*time.Minute).Unix()))
|
||||||
|
email,ok:=u.Get("email")
|
||||||
|
if !ok {
|
||||||
|
return errors.New("send2fa: no email")
|
||||||
|
}
|
||||||
|
firstname,ok:=u.Get("firstname")
|
||||||
|
if !ok {
|
||||||
|
return errors.New("send2fa: no firstname")
|
||||||
|
}
|
||||||
|
lastname,ok:=u.Get("lastname")
|
||||||
|
if !ok {
|
||||||
|
return errors.New("send2fa: no lastname")
|
||||||
|
}
|
||||||
|
fullname:=fmt.Sprintf("%s %s", firstname, lastname)
|
||||||
|
return Send2faEmail(email, fullname, code)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
package scsusers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/base32"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/smtp"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RecoverByUsername(username string) {
|
||||||
|
var email string
|
||||||
|
username = strings.ToLower(username)
|
||||||
|
|
||||||
|
q := fmt.Sprintf("select email from %s_auth where username = ?", c.TablePrefix)
|
||||||
|
err := c.db.Get(&email, q, username)
|
||||||
|
if err != sql.ErrNoRows {
|
||||||
|
recoverycode := randBytes(16)
|
||||||
|
qq := fmt.Sprintf("update %s_auth set recoverycode=?, recoverytime=NOW() where username = ?", c.TablePrefix)
|
||||||
|
_, err := c.db.Exec(qq, recoverycode, username)
|
||||||
|
if err == nil {
|
||||||
|
SendRecoveryEmail(email, username, string(recoverycode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RecoverByEmail(e string) {
|
||||||
|
var username, email string
|
||||||
|
q := fmt.Sprintf("select username from %s_auth where email = ?", c.TablePrefix)
|
||||||
|
err := c.db.Get(&username, q, e)
|
||||||
|
if err != sql.ErrNoRows {
|
||||||
|
recoverycode := randBytes(16)
|
||||||
|
qq := fmt.Sprintf("update %s_auth set recoverycode=?, recoverytime=NOW() where username = ?", c.TablePrefix)
|
||||||
|
_, err := c.db.Exec(qq, recoverycode, username)
|
||||||
|
if err == nil {
|
||||||
|
SendRecoveryEmail(email, username, string(recoverycode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func randBytes(n int) []byte {
|
||||||
|
randomBytes := make([]byte, 32)
|
||||||
|
_, err := rand.Read(randomBytes)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return []byte(base32.StdEncoding.EncodeToString(randomBytes)[:n])
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendRegistrationEmail(recipient, username, password string) bool {
|
||||||
|
data := struct {
|
||||||
|
SiteName string
|
||||||
|
FromEmail string
|
||||||
|
UserName string
|
||||||
|
Pass string
|
||||||
|
}{
|
||||||
|
SiteName: c.SiteName,
|
||||||
|
FromEmail: c.FromEmail,
|
||||||
|
UserName: username,
|
||||||
|
Pass: password,
|
||||||
|
}
|
||||||
|
var body bytes.Buffer
|
||||||
|
err := c.Templates.Registration.Execute(&body, data)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("scsusers.sendRegistrationEmail: Registration template failed to execute: %v returned %s\n", data, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
subject := fmt.Sprintf("Welcome to %s", c.SiteName)
|
||||||
|
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("scsusers.SendRegistrationEmail: Error sending mail to %s: %s\n", recipient, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendAlertEmail(username, recipient, message string) bool {
|
||||||
|
data := struct {
|
||||||
|
SiteName string
|
||||||
|
FromEmail string
|
||||||
|
UserName string
|
||||||
|
Activity string
|
||||||
|
}{
|
||||||
|
SiteName: c.SiteName,
|
||||||
|
FromEmail: c.FromEmail,
|
||||||
|
UserName: username,
|
||||||
|
Activity: message,
|
||||||
|
}
|
||||||
|
var body bytes.Buffer
|
||||||
|
err := c.Templates.Alert.Execute(&body, data)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("scsusers.sendAlertEmail: Alert template failed to execute: %v returned %s\n", data, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
subject := fmt.Sprintf("new Activity Notification on %s", c.SiteName)
|
||||||
|
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("scsusers.sendAlertEmail: Error sending mail to %s: %s\n", recipient, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendRecoveryEmail(recipient, username, code string) bool {
|
||||||
|
data := struct {
|
||||||
|
SiteName string
|
||||||
|
FromEmail string
|
||||||
|
UserName string
|
||||||
|
RecoveryCode string
|
||||||
|
}{
|
||||||
|
SiteName: c.SiteName,
|
||||||
|
FromEmail: c.FromEmail,
|
||||||
|
UserName: username,
|
||||||
|
RecoveryCode: code,
|
||||||
|
}
|
||||||
|
var body bytes.Buffer
|
||||||
|
err := c.Templates.Registration.Execute(&body, data)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("scsusers.sendRecoveryEmail: Recovery template failed to execute: %v returned %s\n", data, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
subject := fmt.Sprintf("Account recovery at %s", c.SiteName)
|
||||||
|
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("scsusers.sendRecoveryEmail: Error sending mail to %s: %s\n", recipient, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func Send2faEmail(recipient, fullname, code string) error {
|
||||||
|
data := struct {
|
||||||
|
SiteName string
|
||||||
|
FromEmail string
|
||||||
|
FullName string
|
||||||
|
Code string
|
||||||
|
}{
|
||||||
|
SiteName: c.SiteName,
|
||||||
|
FromEmail: c.FromEmail,
|
||||||
|
FullName: fullname,
|
||||||
|
Code: code,
|
||||||
|
}
|
||||||
|
var body bytes.Buffer
|
||||||
|
err := c.Templates.TwoFA.Execute(&body, data)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("scsusers.send2fayEmail: 2fa template failed to execute: %v returned %s", data, err.Error())
|
||||||
|
}
|
||||||
|
subject := fmt.Sprintf("Two Factor Authentication Code at %s", c.SiteName)
|
||||||
|
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendMail(addr, from, subject, body string, to string) error {
|
||||||
|
r := strings.NewReplacer("\r\n", "", "\r", "", "\n", "", "%0a", "", "%0d", "")
|
||||||
|
|
||||||
|
c, err := smtp.Dial(addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
if err = c.Mail(r.Replace(from)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
to = r.Replace(to)
|
||||||
|
if err = c.Rcpt(to); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w, err := c.Data()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
date := time.Now()
|
||||||
|
msg := "To: " + to + "\r\n" +
|
||||||
|
"From: " + from + "\r\n" +
|
||||||
|
"Subject: " + subject + "\r\n" +
|
||||||
|
"Content-Type: text/html; charset=\"UTF-8\"\r\n" +
|
||||||
|
"Date: " + date.Format(time.RFC1123Z) + "\r\n" +
|
||||||
|
"\r\n" + body
|
||||||
|
|
||||||
|
_, err = w.Write([]byte(msg))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = w.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.Quit()
|
||||||
|
}
|
222
main.go
222
main.go
|
@ -1,17 +1,12 @@
|
||||||
package scsusers
|
package scsusers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/base32"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
"net/smtp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
@ -21,6 +16,7 @@ type templates struct {
|
||||||
Registration *template.Template
|
Registration *template.Template
|
||||||
Alert *template.Template
|
Alert *template.Template
|
||||||
Recovery *template.Template
|
Recovery *template.Template
|
||||||
|
TwoFA *template.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
|
@ -59,6 +55,7 @@ func Init(dbin *sqlx.DB, tp, sitename, fromaddr, smtpserver string) {
|
||||||
SetRegistrationTemplate("")
|
SetRegistrationTemplate("")
|
||||||
SetAlertTemplate("")
|
SetAlertTemplate("")
|
||||||
SetRecoveryTemplate("")
|
SetRecoveryTemplate("")
|
||||||
|
Set2faTemplate("")
|
||||||
}
|
}
|
||||||
|
|
||||||
func UsernameAvailable(username string) bool {
|
func UsernameAvailable(username string) bool {
|
||||||
|
@ -307,218 +304,3 @@ func SetMeta(username string, metakey string, metavalue string) {
|
||||||
log.Printf("scsusers.SetMeta: %s %s %s %s\n", username, metakey, metavalue, err.Error())
|
log.Printf("scsusers.SetMeta: %s %s %s %s\n", username, metakey, metavalue, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecoverByUsername(username string) {
|
|
||||||
var email string
|
|
||||||
username = strings.ToLower(username)
|
|
||||||
|
|
||||||
q := fmt.Sprintf("select email from %s_auth where username = ?", c.TablePrefix)
|
|
||||||
err := c.db.Get(&email, q, username)
|
|
||||||
if err != sql.ErrNoRows {
|
|
||||||
recoverycode := randBytes(16)
|
|
||||||
qq := fmt.Sprintf("update %s_auth set recoverycode=?, recoverytime=NOW() where username = ?", c.TablePrefix)
|
|
||||||
_, err := c.db.Exec(qq, recoverycode, username)
|
|
||||||
if err == nil {
|
|
||||||
SendRecoveryEmail(email, username, string(recoverycode))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func RecoverByEmail(e string) {
|
|
||||||
var username, email string
|
|
||||||
q := fmt.Sprintf("select username from %s_auth where email ILIKE ?", c.TablePrefix)
|
|
||||||
err := c.db.Get(&username, q, e)
|
|
||||||
if err != sql.ErrNoRows {
|
|
||||||
recoverycode := randBytes(16)
|
|
||||||
qq := fmt.Sprintf("update %s_auth set recoverycode=?, recoverytime=NOW() where username = ?", c.TablePrefix)
|
|
||||||
_, err := c.db.Exec(qq, recoverycode, username)
|
|
||||||
if err == nil {
|
|
||||||
SendRecoveryEmail(email, username, string(recoverycode))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func randBytes(n int) []byte {
|
|
||||||
randomBytes := make([]byte, 32)
|
|
||||||
_, err := rand.Read(randomBytes)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return []byte(base32.StdEncoding.EncodeToString(randomBytes)[:n])
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendRegistrationEmail(recipient, username, password string) bool {
|
|
||||||
data := struct {
|
|
||||||
SiteName string
|
|
||||||
FromEmail string
|
|
||||||
UserName string
|
|
||||||
Pass string
|
|
||||||
}{
|
|
||||||
SiteName: c.SiteName,
|
|
||||||
FromEmail: c.FromEmail,
|
|
||||||
UserName: username,
|
|
||||||
Pass: password,
|
|
||||||
}
|
|
||||||
var body bytes.Buffer
|
|
||||||
err := c.Templates.Registration.Execute(&body, data)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("scsusers.sendRegistrationEmail: Registration template failed to execute: %v returned %s\n", data, err.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
subject := fmt.Sprintf("Welcome to %s", c.SiteName)
|
|
||||||
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("scsusers.SendRegistrationEmail: Error sending mail to %s: %s\n", recipient, err.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendAlertEmail(username, recipient, message string) bool {
|
|
||||||
data := struct {
|
|
||||||
SiteName string
|
|
||||||
FromEmail string
|
|
||||||
UserName string
|
|
||||||
Activity string
|
|
||||||
}{
|
|
||||||
SiteName: c.SiteName,
|
|
||||||
FromEmail: c.FromEmail,
|
|
||||||
UserName: username,
|
|
||||||
Activity: message,
|
|
||||||
}
|
|
||||||
var body bytes.Buffer
|
|
||||||
err := c.Templates.Alert.Execute(&body, data)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("scsusers.sendAlertEmail: Alert template failed to execute: %v returned %s\n", data, err.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
subject := fmt.Sprintf("new Activity Notification on %s", c.SiteName)
|
|
||||||
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("scsusers.sendAlertEmail: Error sending mail to %s: %s\n", recipient, err.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendRecoveryEmail(recipient, username, code string) bool {
|
|
||||||
data := struct {
|
|
||||||
SiteName string
|
|
||||||
FromEmail string
|
|
||||||
UserName string
|
|
||||||
RecoveryCode string
|
|
||||||
}{
|
|
||||||
SiteName: c.SiteName,
|
|
||||||
FromEmail: c.FromEmail,
|
|
||||||
UserName: username,
|
|
||||||
RecoveryCode: code,
|
|
||||||
}
|
|
||||||
var body bytes.Buffer
|
|
||||||
err := c.Templates.Registration.Execute(&body, data)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("scsusers.sendRecoveryEmail: Recovery template failed to execute: %v returned %s\n", data, err.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
subject := fmt.Sprintf("Account recovery at %s", c.SiteName)
|
|
||||||
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("scsusers.sendRecoveryEmail: Error sending mail to %s: %s\n", recipient, err.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetRegistrationTemplate(t string) bool {
|
|
||||||
if len(t) != 0 {
|
|
||||||
r, err := template.New("reg").Parse(t)
|
|
||||||
if err != nil {
|
|
||||||
c.Templates.Registration = r
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
df := `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html></head><body><p>Hello {{.UserName}}! Welcome to {{.SiteName}}! We've created your account with the username you selected and the following password: {{.Pass}}<br>You can change your password to whatever you want once you log in.</p></body></html>`
|
|
||||||
|
|
||||||
r, err := template.New("reg").Parse(df)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("scsusers.SetRegistrationTemplate: Default registration template MUST compile. Error: " + err.Error())
|
|
||||||
}
|
|
||||||
c.Templates.Registration = r
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetAlertTemplate(t string) bool {
|
|
||||||
if len(t) != 0 {
|
|
||||||
r, err := template.New("alert").Parse(t)
|
|
||||||
if err != nil {
|
|
||||||
c.Templates.Alert = r
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
df := `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html></head><body><p> Hey {{.UserName}}! Just letting you know that {{.Activity}}.<br> You can disable future notifications in your user settings.</p></body></html>`
|
|
||||||
r, err := template.New("alert").Parse(df)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("scsusers.SetAlertTemplate: Default alert template MUST compile. Error: " + err.Error())
|
|
||||||
}
|
|
||||||
c.Templates.Alert = r
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetRecoveryTemplate(t string) bool {
|
|
||||||
if len(t) != 0 {
|
|
||||||
r, err := template.New("recovery").Parse(t)
|
|
||||||
if err != nil {
|
|
||||||
c.Templates.Recovery = r
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
df := `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html></head><body><p>Hello {{.UserName}}! Someone (hopefully you) has attempted an account recovery agt {{.SiteName}}. If this was yousername, enter the following code to regain access: {{.RecoveryCode}}<br> If this was not yousername, you can ignore this email.</p></body></html>`
|
|
||||||
r, err := template.New("recovery").Parse(df)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("scsusers.SetRecoveryTemplate: Default recovery template MUST compile. Error: " + err.Error())
|
|
||||||
}
|
|
||||||
c.Templates.Recovery = r
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendMail(addr, from, subject, body string, to string) error {
|
|
||||||
r := strings.NewReplacer("\r\n", "", "\r", "", "\n", "", "%0a", "", "%0d", "")
|
|
||||||
|
|
||||||
c, err := smtp.Dial(addr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer c.Close()
|
|
||||||
if err = c.Mail(r.Replace(from)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
to = r.Replace(to)
|
|
||||||
if err = c.Rcpt(to); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
w, err := c.Data()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
date := time.Now()
|
|
||||||
msg := "To: " + to + "\r\n" +
|
|
||||||
"From: " + from + "\r\n" +
|
|
||||||
"Subject: " + subject + "\r\n" +
|
|
||||||
"Content-Type: text/html; charset=\"UTF-8\"\r\n" +
|
|
||||||
"Date: " + date.Format(time.RFC1123Z) + "\r\n" +
|
|
||||||
"\r\n" + body
|
|
||||||
|
|
||||||
_, err = w.Write([]byte(msg))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = w.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.Quit()
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package scsusers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"html/template"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed templates/*.html
|
||||||
|
var FS embed.FS
|
||||||
|
|
||||||
|
func SetRegistrationTemplate(t string) bool {
|
||||||
|
if len(t) != 0 {
|
||||||
|
r, err := template.New("reg").Parse(t)
|
||||||
|
if err != nil {
|
||||||
|
c.Templates.Registration = r
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
df, err := FS.ReadFile("templates/registration.html")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Missing recovery template")
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := template.New("reg").Parse(string(df))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("scsusers.SetRegistrationTemplate: Default registration template MUST compile. Error: " + err.Error())
|
||||||
|
}
|
||||||
|
c.Templates.Registration = r
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func Set2faTemplate(t string) bool {
|
||||||
|
if len(t) != 0 {
|
||||||
|
r, err := template.New("2fa").Parse(t)
|
||||||
|
if err != nil {
|
||||||
|
c.Templates.Registration = r
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
df, err := FS.ReadFile("templates/2fa.html")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Missing 2fa template")
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := template.New("2fa").Parse(string(df))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("scsusers.Set2faTemplate: Default 2fa template MUST compile. Error: " + err.Error())
|
||||||
|
}
|
||||||
|
c.Templates.Registration = r
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetAlertTemplate(t string) bool {
|
||||||
|
if len(t) != 0 {
|
||||||
|
r, err := template.New("alert").Parse(t)
|
||||||
|
if err != nil {
|
||||||
|
c.Templates.Alert = r
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
df, err := FS.ReadFile("templates/alert.html")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Missing recovery template")
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := template.New("alert").Parse(string(df))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("scsusers.SetAlertTemplate: Default alert template MUST compile. Error: " + err.Error())
|
||||||
|
}
|
||||||
|
c.Templates.Alert = r
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetRecoveryTemplate(t string) bool {
|
||||||
|
if len(t) != 0 {
|
||||||
|
r, err := template.New("recovery").Parse(t)
|
||||||
|
if err != nil {
|
||||||
|
c.Templates.Recovery = r
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
df, err := FS.ReadFile("templates/recovery.html")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Missing recovery template")
|
||||||
|
}
|
||||||
|
r, err := template.New("recovery").Parse(string(df))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("scsusers.SetRecoveryTemplate: Default recovery template MUST compile. Error: " + err.Error())
|
||||||
|
}
|
||||||
|
c.Templates.Recovery = r
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Hello {{.UserName}}! This is your Two Factor Authentication code to finish logging in to {{.SiteName}}. If you did not request this code,
|
||||||
|
please contact us immediately. This code will expire in 30 minutes.<br><br>
|
||||||
|
<h1>Your 2FA code is: {{.Code}}</h1>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html
|
||||||
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p> Hey {{.UserName}}! Just letting you know that {{.Activity}}.<br> You can disable future notifications in your
|
||||||
|
user settings.</p>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html
|
||||||
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>Hello {{.UserName}}! Someone (hopefully you) has attempted an account recovery at {{.SiteName}}. If this was
|
||||||
|
you, enter the following code to regain access: {{.RecoveryCode}}<br> If this was not you, you can safely
|
||||||
|
ignore this email.</p>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -7,7 +7,7 @@
|
||||||
<body>
|
<body>
|
||||||
<p>
|
<p>
|
||||||
Hello {{.UserName}}! Welcome to {{.SiteName}}! We've created your account with the username you selected and the following password: {{.Pass}}<br>
|
Hello {{.UserName}}! Welcome to {{.SiteName}}! We've created your account with the username you selected and the following password: {{.Pass}}<br>
|
||||||
You can change your password to whatever you want once you log in.
|
You can change your password once you log in.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in New Issue