Adding code
This commit is contained in:
parent
078de6ce8b
commit
7432a08a46
|
@ -0,0 +1,201 @@
|
||||||
|
package scsusers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"html/template"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"net/smtp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type templates struct {
|
||||||
|
Registration *template.Template
|
||||||
|
Alert *template.Template
|
||||||
|
Recovery *template.Template
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
SiteName string
|
||||||
|
FromEmail string
|
||||||
|
Templates templates
|
||||||
|
db *sqlx.DB
|
||||||
|
TablePrefix string
|
||||||
|
}
|
||||||
|
|
||||||
|
var c config
|
||||||
|
|
||||||
|
func Init(dbin *sqlx.DB, tp, sitename, fromaddr string) {
|
||||||
|
c.db = dbin
|
||||||
|
c.TablePrefix = tp
|
||||||
|
c.SiteName = sitename
|
||||||
|
c.FromEmail = fromaddr
|
||||||
|
|
||||||
|
SetRegistrationTemplate("")
|
||||||
|
SetAlertTemplate("")
|
||||||
|
SetRecoveryTemplate("")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func UsernameAvailable(username string) bool {
|
||||||
|
|
||||||
|
q := fmt.Sprintf("select username from %s_auth where username=$1", c.TablePrefix)
|
||||||
|
err := c.db.Get(q, username)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for username availability, add to database, send email */
|
||||||
|
|
||||||
|
func Register(username, email, ip string) bool {
|
||||||
|
if !UsernameAvailable(username) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
pass := randBytes(16)
|
||||||
|
crypt, err := bcrypt.GenerateFromPassword(pass, 20)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Bcrypt GenerateFromPassword failed? Pass is %s and error is %s\n", pass, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
q := fmt.Sprintf("insert into %s_auth (username, email, password, registration_date, registration_ip) values ($1, $2, $3, NOW(), $4)", c.TablePrefix)
|
||||||
|
_, err = c.db.Exec(q, username, email, crypt, ip)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func randBytes(n int) []byte {
|
||||||
|
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
b := make([]byte, n)
|
||||||
|
for i := range b {
|
||||||
|
b[i] = letterBytes[rand.Intn(len(letterBytes))]
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
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("Registration template failed to execute: %v returned %s\n", data, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
subject := fmt.Sprintf("Welcome to %s", c.SiteName)
|
||||||
|
err = SendMail("localhost:25", c.FromEmail, subject, body.String(), recipient)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("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("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> Hello {{.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("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 you, enter the following code to regain access: {{.RecoveryCode}}<br> If this was not you, you can ignore this email.</p></body></html>`
|
||||||
|
r, err := template.New("recovery").Parse(df)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Default alert 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
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := "To: " + to + "\r\n" +
|
||||||
|
"From: " + from + "\r\n" +
|
||||||
|
"Subject: " + subject + "\r\n" +
|
||||||
|
"Content-Type: text/html; charset=\"UTF-8\"\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,15 @@
|
||||||
|
<!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>
|
Loading…
Reference in New Issue