mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
make checkInvite check only one invite, invite daemon
checkInvite no longer loops over all invites and checks for expiry, that functionality has moved to checkInvites. Couple more rogue print statements removed aswell.
This commit is contained in:
parent
dba20bd3ea
commit
4e16f6fd48
84
api.go
84
api.go
@ -76,12 +76,11 @@ func timeDiff(a, b time.Time) (year, month, day, hour, min, sec int) {
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx *appContext) checkInvite(code string, used bool, username string) bool {
|
||||
func (ctx *appContext) checkInvites() {
|
||||
current_time := time.Now()
|
||||
ctx.storage.loadInvites()
|
||||
match := false
|
||||
changed := false
|
||||
for invCode, data := range ctx.storage.invites {
|
||||
for code, data := range ctx.storage.invites {
|
||||
expiry := data.ValidTill
|
||||
if current_time.After(expiry) {
|
||||
ctx.debug.Printf("Housekeeping: Deleting old invite %s", code)
|
||||
@ -90,7 +89,7 @@ func (ctx *appContext) checkInvite(code string, used bool, username string) bool
|
||||
ctx.debug.Printf("%s: Expiry notification", code)
|
||||
for address, settings := range notify {
|
||||
if settings["notify-expiry"] {
|
||||
if ctx.email.constructExpiry(invCode, data, ctx) != nil {
|
||||
if ctx.email.constructExpiry(code, data, ctx) != nil {
|
||||
ctx.err.Printf("%s: Failed to construct expiry notification", code)
|
||||
} else if ctx.email.send(address, ctx) != nil {
|
||||
ctx.err.Printf("%s: Failed to send expiry notification", code)
|
||||
@ -101,31 +100,62 @@ func (ctx *appContext) checkInvite(code string, used bool, username string) bool
|
||||
}
|
||||
}
|
||||
changed = true
|
||||
delete(ctx.storage.invites, invCode)
|
||||
} else if invCode == code {
|
||||
match = true
|
||||
if used {
|
||||
changed = true
|
||||
del := false
|
||||
newInv := data
|
||||
if newInv.RemainingUses == 1 {
|
||||
del = true
|
||||
delete(ctx.storage.invites, invCode)
|
||||
} else if newInv.RemainingUses != 0 {
|
||||
// 0 means infinite i guess?
|
||||
newInv.RemainingUses -= 1
|
||||
}
|
||||
newInv.UsedBy = append(newInv.UsedBy, []string{username, ctx.formatDatetime(current_time)})
|
||||
if !del {
|
||||
ctx.storage.invites[invCode] = newInv
|
||||
}
|
||||
}
|
||||
delete(ctx.storage.invites, code)
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
ctx.storage.storeInvites()
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
func (ctx *appContext) checkInvite(code string, used bool, username string) bool {
|
||||
current_time := time.Now()
|
||||
ctx.storage.loadInvites()
|
||||
changed := false
|
||||
if inv, match := ctx.storage.invites[code]; match {
|
||||
expiry := inv.ValidTill
|
||||
if current_time.After(expiry) {
|
||||
ctx.debug.Printf("Housekeeping: Deleting old invite %s", code)
|
||||
notify := inv.Notify
|
||||
if ctx.config.Section("notifications").Key("enabled").MustBool(false) && len(notify) != 0 {
|
||||
ctx.debug.Printf("%s: Expiry notification", code)
|
||||
for address, settings := range notify {
|
||||
if settings["notify-expiry"] {
|
||||
if ctx.email.constructExpiry(code, inv, ctx) != nil {
|
||||
ctx.err.Printf("%s: Failed to construct expiry notification", code)
|
||||
} else if ctx.email.send(address, ctx) != nil {
|
||||
ctx.err.Printf("%s: Failed to send expiry notification", code)
|
||||
} else {
|
||||
ctx.info.Printf("Sent expiry notification to %s", address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
changed = true
|
||||
match = false
|
||||
delete(ctx.storage.invites, code)
|
||||
} else if used {
|
||||
changed = true
|
||||
del := false
|
||||
newInv := inv
|
||||
if newInv.RemainingUses == 1 {
|
||||
del = true
|
||||
delete(ctx.storage.invites, code)
|
||||
} else if newInv.RemainingUses != 0 {
|
||||
// 0 means infinite i guess?
|
||||
newInv.RemainingUses -= 1
|
||||
}
|
||||
newInv.UsedBy = append(newInv.UsedBy, []string{username, ctx.formatDatetime(current_time)})
|
||||
if !del {
|
||||
ctx.storage.invites[code] = newInv
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
ctx.storage.storeInvites()
|
||||
}
|
||||
return match
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Routes from now on!
|
||||
@ -270,12 +300,8 @@ func (ctx *appContext) GenerateInvite(gc *gin.Context) {
|
||||
func (ctx *appContext) GetInvites(gc *gin.Context) {
|
||||
ctx.debug.Println("Invites requested")
|
||||
current_time := time.Now()
|
||||
// checking one checks all of them
|
||||
ctx.storage.loadInvites()
|
||||
for key := range ctx.storage.invites {
|
||||
ctx.checkInvite(key, false, "")
|
||||
break
|
||||
}
|
||||
ctx.checkInvites()
|
||||
var invites []map[string]interface{}
|
||||
for code, inv := range ctx.storage.invites {
|
||||
_, _, days, hours, minutes, _ := timeDiff(inv.ValidTill, current_time)
|
||||
|
3
auth.go
3
auth.go
@ -16,9 +16,6 @@ func (ctx *appContext) webAuth() gin.HandlerFunc {
|
||||
}
|
||||
|
||||
func (ctx *appContext) authenticate(gc *gin.Context) {
|
||||
for _, val := range ctx.users {
|
||||
fmt.Println("userid", val.UserID)
|
||||
}
|
||||
header := strings.SplitN(gc.Request.Header.Get("Authorization"), " ", 2)
|
||||
if header[0] != "Basic" {
|
||||
ctx.debug.Println("Invalid authentication header")
|
||||
|
50
daemon.go
Normal file
50
daemon.go
Normal file
@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import "time"
|
||||
|
||||
// https://bbengfort.github.io/snippets/2016/06/26/background-work-goroutines-timer.html THANKS
|
||||
|
||||
type Repeater struct {
|
||||
Stopped bool
|
||||
ShutdownChannel chan string
|
||||
Interval time.Duration
|
||||
period time.Duration
|
||||
ctx *appContext
|
||||
}
|
||||
|
||||
func NewRepeater(interval time.Duration, ctx *appContext) *Repeater {
|
||||
return &Repeater{
|
||||
Stopped: false,
|
||||
ShutdownChannel: make(chan string),
|
||||
Interval: interval,
|
||||
period: interval,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *Repeater) Run() {
|
||||
rt.ctx.info.Println("Invite daemon started")
|
||||
for {
|
||||
select {
|
||||
case <-rt.ShutdownChannel:
|
||||
rt.ShutdownChannel <- "Down"
|
||||
return
|
||||
case <-time.After(rt.period):
|
||||
break
|
||||
}
|
||||
started := time.Now()
|
||||
rt.ctx.storage.loadInvites()
|
||||
rt.ctx.debug.Println("Daemon: Checking invites")
|
||||
rt.ctx.checkInvites()
|
||||
finished := time.Now()
|
||||
duration := finished.Sub(started)
|
||||
rt.period = rt.Interval - duration
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *Repeater) Shutdown() {
|
||||
rt.Stopped = true
|
||||
rt.ShutdownChannel <- "Down"
|
||||
<-rt.ShutdownChannel
|
||||
close(rt.ShutdownChannel)
|
||||
}
|
40
email.go
40
email.go
@ -73,7 +73,6 @@ func (email *Emailer) constructInvite(code string, invite Invite, ctx *appContex
|
||||
fpath := ctx.config.Section("invite_emails").Key("email_" + key).String()
|
||||
tpl, err := template.ParseFiles(fpath)
|
||||
if err != nil {
|
||||
fmt.Println("failed email", err)
|
||||
return err
|
||||
}
|
||||
var tplData bytes.Buffer
|
||||
@ -85,7 +84,6 @@ func (email *Emailer) constructInvite(code string, invite Invite, ctx *appContex
|
||||
"message": message,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("failed email", err)
|
||||
return err
|
||||
}
|
||||
if key == "html" {
|
||||
@ -105,7 +103,6 @@ func (email *Emailer) constructExpiry(code string, invite Invite, ctx *appContex
|
||||
fpath := ctx.config.Section("notifications").Key("expiry_" + key).String()
|
||||
tpl, err := template.ParseFiles(fpath)
|
||||
if err != nil {
|
||||
fmt.Println("failed email", err)
|
||||
return err
|
||||
}
|
||||
var tplData bytes.Buffer
|
||||
@ -114,7 +111,6 @@ func (email *Emailer) constructExpiry(code string, invite Invite, ctx *appContex
|
||||
"expiry": expiry,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("failed email", err)
|
||||
return err
|
||||
}
|
||||
if key == "html" {
|
||||
@ -140,7 +136,6 @@ func (email *Emailer) constructCreated(code, username, address string, invite In
|
||||
fpath := ctx.config.Section("notifications").Key("created_" + key).String()
|
||||
tpl, err := template.ParseFiles(fpath)
|
||||
if err != nil {
|
||||
fmt.Println("failed email", err)
|
||||
return err
|
||||
}
|
||||
var tplData bytes.Buffer
|
||||
@ -151,7 +146,6 @@ func (email *Emailer) constructCreated(code, username, address string, invite In
|
||||
"time": created,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("failed email", err)
|
||||
return err
|
||||
}
|
||||
if key == "html" {
|
||||
@ -166,33 +160,6 @@ func (email *Emailer) constructCreated(code, username, address string, invite In
|
||||
|
||||
func (email *Emailer) send(address string, ctx *appContext) error {
|
||||
if email.sendMethod == "mailgun" {
|
||||
// reqData := map[string]string{
|
||||
// "to": fmt.Sprintf("%s <%s>", "test", email.to),
|
||||
// "from": email.fromAddr,
|
||||
// "subject": email.subject,
|
||||
// }
|
||||
// if email.sendType == "invite" {
|
||||
// reqData["text"] = email.invite.text
|
||||
// reqData["html"] = email.invite.html
|
||||
// }
|
||||
// data := &bytes.Buffer{}
|
||||
// encoder := json.NewEncoder(data)
|
||||
// encoder.SetEscapeHTML(false)
|
||||
// err := encoder.Encode(reqData)
|
||||
// fmt.Println("marshaled:", data)
|
||||
// if err != nil {
|
||||
// fmt.Println("Failed marshal:", err, ">", data)
|
||||
// return err
|
||||
// }
|
||||
// var req *http.Request
|
||||
// req, err = http.NewRequest("POST", ctx.config.Section("mailgun").Key("api_url").String(), data)
|
||||
// req.SetBasicAuth("api", ctx.config.Section("mailgun").Key("api_key").String())
|
||||
// var resp *http.Response
|
||||
// resp, err = email.httpClient.Do(req)
|
||||
// if err != nil || !(resp.StatusCode == 200 || resp.StatusCode == 204) {
|
||||
// fmt.Println("failed send:", err, resp.StatusCode)
|
||||
// fmt.Println("resp:", resp.Header.Get("Content-Encoding"), resp.Body)
|
||||
// }
|
||||
message := email.mg.NewMessage(
|
||||
fmt.Sprintf("%s <%s>", email.fromName, email.fromAddr),
|
||||
email.content.subject,
|
||||
@ -201,9 +168,10 @@ func (email *Emailer) send(address string, ctx *appContext) error {
|
||||
message.SetHtml(email.content.html)
|
||||
mgctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
|
||||
defer cancel()
|
||||
_, id, err := email.mg.Send(mgctx, message)
|
||||
fmt.Println("mailgun:", id, err)
|
||||
|
||||
_, _, err := email.mg.Send(mgctx, message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
4
main.go
4
main.go
@ -13,6 +13,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Username is JWT!
|
||||
@ -193,6 +194,9 @@ func main() {
|
||||
|
||||
ctx.email.init(ctx)
|
||||
|
||||
inviteDaemon := NewRepeater(time.Duration(60*time.Second), ctx)
|
||||
go inviteDaemon.Run()
|
||||
|
||||
ctx.info.Println("Loading routes")
|
||||
router := gin.New()
|
||||
|
||||
|
@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -78,8 +77,6 @@ func loadJSON(path string, obj interface{}) error {
|
||||
}
|
||||
|
||||
func storeJSON(path string, obj interface{}) error {
|
||||
test := json.NewEncoder(os.Stdout)
|
||||
test.Encode(obj)
|
||||
data, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
|
Loading…
Reference in New Issue
Block a user