go fmt; email message after payment

This commit is contained in:
Joerg Lehmann 2020-04-09 14:41:41 +02:00
parent 2cac4d56e2
commit 5548949e9d
9 changed files with 791 additions and 795 deletions

View File

@ -1,11 +1,11 @@
package main package main
import ( import (
"crypto/md5"
"encoding/hex"
"fmt"
"github.com/gorilla/securecookie" "github.com/gorilla/securecookie"
"net/http" "net/http"
"fmt"
"crypto/md5"
"encoding/hex"
) )
// cookie handling // cookie handling
@ -31,9 +31,9 @@ func getUserNameHash(request *http.Request) (userName string) {
userName = cookieValue["name"] userName = cookieValue["name"]
} }
} }
hasher := md5.New() hasher := md5.New()
hasher.Write([]byte(userName)) hasher.Write([]byte(userName))
return hex.EncodeToString(hasher.Sum(nil)) return hex.EncodeToString(hasher.Sum(nil))
} }
func setSession(userName string, response http.ResponseWriter) { func setSession(userName string, response http.ResponseWriter) {
@ -67,34 +67,33 @@ func loginHandler(response http.ResponseWriter, request *http.Request) {
pass := request.FormValue("password") pass := request.FormValue("password")
redirectTarget := "/invalid_login.html" redirectTarget := "/invalid_login.html"
// .. check credentials .. // .. check credentials ..
if checkLoginCredentials(name,pass) { if checkLoginCredentials(name, pass) {
redirectTarget = "/scales.html" redirectTarget = "/scales.html"
logit(fmt.Sprintf("loginHandler: successful login for User %s",name)) logit(fmt.Sprintf("loginHandler: successful login for User %s", name))
setSession(name, response) setSession(name, response)
updateLoginTime(name) updateLoginTime(name)
} else { } else {
logit(fmt.Sprintf("loginHandler: invalid login for User %s",name)) logit(fmt.Sprintf("loginHandler: invalid login for User %s", name))
} }
http.Redirect(response, request, redirectTarget, 302) http.Redirect(response, request, redirectTarget, 302)
} }
// resetPassword handler // resetPassword handler
func resetPasswordHandler(response http.ResponseWriter, request *http.Request) { func resetPasswordHandler(response http.ResponseWriter, request *http.Request) {
name := request.FormValue("email") name := request.FormValue("email")
pass := request.FormValue("password") pass := request.FormValue("password")
redirectTarget := "/" redirectTarget := "/"
logit(fmt.Sprintf("resetPasswordHandler: request for User %s",name)) logit(fmt.Sprintf("resetPasswordHandler: request for User %s", name))
if name != "" && pass != "" { if name != "" && pass != "" {
if checkUserAvailable(name) { if checkUserAvailable(name) {
http.Redirect(response, request, "/user_does_not_exist.html", 302) http.Redirect(response, request, "/user_does_not_exist.html", 302)
} else { } else {
updateUser(name,pass) updateUser(name, pass)
http.Redirect(response, request, redirectTarget, 302) http.Redirect(response, request, redirectTarget, 302)
} }
} }
http.Redirect(response, request, "/error_reset_password.html",302) http.Redirect(response, request, "/error_reset_password.html", 302)
} }
// setPassword handler // setPassword handler
@ -104,10 +103,10 @@ func setPasswordHandler(response http.ResponseWriter, request *http.Request) {
pass := request.FormValue("password") pass := request.FormValue("password")
if name != "" && pass != "" { if name != "" && pass != "" {
if checkUserAvailable(name) { if checkUserAvailable(name) {
http.Redirect(response, request, "/user_does_not_exist.html", 302) http.Redirect(response, request, "/user_does_not_exist.html", 302)
} else { } else {
updateUser(name,pass) updateUser(name, pass)
} }
} }
} }
@ -122,7 +121,7 @@ func logoutHandler(response http.ResponseWriter, request *http.Request) {
func confirmHandler(response http.ResponseWriter, request *http.Request) { func confirmHandler(response http.ResponseWriter, request *http.Request) {
confirm_id := request.URL.Query().Get("id") confirm_id := request.URL.Query().Get("id")
logit(fmt.Sprintf("Confirm ID: %s\n",confirm_id)) logit(fmt.Sprintf("Confirm ID: %s\n", confirm_id))
confirmUser(confirm_id) confirmUser(confirm_id)
http.Redirect(response, request, "/", 302) http.Redirect(response, request, "/", 302)
} }

View File

@ -1,17 +1,17 @@
package main package main
import ( import (
"log" "log"
) )
// Contains tells whether a contains x. // Contains tells whether a contains x.
func Contains(a []string, x string) bool { func Contains(a []string, x string) bool {
log.Println("Search for: "+x) log.Println("Search for: " + x)
for _, n := range a { for _, n := range a {
log.Println("Piece of Array: "+n) log.Println("Piece of Array: " + n)
if x == n { if x == n {
return true return true
} }
} }
return false return false
} }

2
log.go
View File

@ -5,5 +5,5 @@ import (
) )
func logit(log_message string) { func logit(log_message string) {
log.Println(log_message) log.Println(log_message)
} }

78
mail.go
View File

@ -1,26 +1,26 @@
package main package main
import ( import (
"log"
"bytes" "bytes"
"log"
"net/smtp" "net/smtp"
) )
func sendEmail(username,confirm_id string) { func sendEmail(username, confirm_id string) {
c, err := smtp.Dial("127.0.0.1:25") c, err := smtp.Dial("127.0.0.1:25")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer c.Close() defer c.Close()
// Set the sender and recipient. // Set the sender and recipient.
c.Mail("register@mini-beieli.ch") c.Mail("register@mini-beieli.ch")
c.Rcpt(username) c.Rcpt(username)
// Send the email body. // Send the email body.
wc, err := c.Data() wc, err := c.Data()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer wc.Close() defer wc.Close()
mail_message := "To: " + username + ` mail_message := "To: " + username + `
Subject: Passwortaenderung auf https://mini-beieli.ch, bitte bestaetigen Subject: Passwortaenderung auf https://mini-beieli.ch, bitte bestaetigen
@ -37,27 +37,27 @@ Mit freundlichen Grüssen
-- --
mini-beieli.ch` mini-beieli.ch`
buf := bytes.NewBufferString(mail_message) buf := bytes.NewBufferString(mail_message)
if _, err = buf.WriteTo(wc); err != nil { if _, err = buf.WriteTo(wc); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
func sendPaymentConfirmationEmail(username,charge_data string, amount int64) { func sendPaymentConfirmationEmail(username, charge_data string, amount int64) {
c, err := smtp.Dial("127.0.0.1:25") c, err := smtp.Dial("127.0.0.1:25")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer c.Close() defer c.Close()
// Set the sender and recipient. // Set the sender and recipient.
c.Mail("info@mini-beieli.ch") c.Mail("info@mini-beieli.ch")
c.Rcpt(username) c.Rcpt(username)
// Send the email body. // Send the email body.
wc, err := c.Data() wc, err := c.Data()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer wc.Close() defer wc.Close()
mail_message := "To: " + username + ` mail_message := "To: " + username + `
Subject: Zahlungsbestaetigung mini-beieli.ch Subject: Zahlungsbestaetigung mini-beieli.ch
@ -71,8 +71,8 @@ Mit freundlichen Grüssen
-- --
mini-beieli.ch` mini-beieli.ch`
buf := bytes.NewBufferString(mail_message) buf := bytes.NewBufferString(mail_message)
if _, err = buf.WriteTo(wc); err != nil { if _, err = buf.WriteTo(wc); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

78
main.go
View File

@ -5,11 +5,11 @@ import (
"net/http" "net/http"
"os" "os"
"path" "path"
"time" "time"
) )
func serveTemplate(w http.ResponseWriter, r *http.Request) { func serveTemplate(w http.ResponseWriter, r *http.Request) {
logit("Called URL: "+r.URL.Path) logit("Called URL: " + r.URL.Path)
// wennn kein File angegeben ist: index.html // wennn kein File angegeben ist: index.html
if r.URL.Path == "/" { if r.URL.Path == "/" {
r.URL.Path = "/index.html" r.URL.Path = "/index.html"
@ -35,36 +35,36 @@ func serveTemplate(w http.ResponseWriter, r *http.Request) {
return return
} }
var userName = getUserName(r) var userName = getUserName(r)
t := time.Now() t := time.Now()
var datetimestring = t.Format("20060102150405") var datetimestring = t.Format("20060102150405")
var scales = getMyDevs(userName) var scales = getMyDevs(userName)
var last_metrics []OneMetric var last_metrics []OneMetric
query_values := r.URL.Query() query_values := r.URL.Query()
if (r.URL.Path == "/scales.html") { if r.URL.Path == "/scales.html" {
// wir holen noch die letzten Metriken // wir holen noch die letzten Metriken
for _, v := range scales { for _, v := range scales {
last_metric := getLastMetrics(v) last_metric := getLastMetrics(v)
last_metrics = append(last_metrics, last_metric) last_metrics = append(last_metrics, last_metric)
} }
} }
data := struct { data := struct {
UserName string UserName string
DateTimeString string DateTimeString string
Scales []string Scales []string
LastMetrics []OneMetric LastMetrics []OneMetric
QueryValues map[string][]string QueryValues map[string][]string
} { }{
userName, userName,
datetimestring, datetimestring,
scales, scales,
last_metrics, last_metrics,
query_values, query_values,
} }
if err := tmpl.ExecuteTemplate(w, "layout", &data); err != nil { if err := tmpl.ExecuteTemplate(w, "layout", &data); err != nil {
logit(err.Error()) logit(err.Error())
@ -73,23 +73,23 @@ func serveTemplate(w http.ResponseWriter, r *http.Request) {
} }
func main() { func main() {
initDB() initDB()
defer closeDB() defer closeDB()
fs := http.FileServer(http.Dir("static")) fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs)) http.Handle("/static/", http.StripPrefix("/static/", fs))
http.Handle("/favicon.ico", fs) http.Handle("/favicon.ico", fs)
http.HandleFunc("/", serveTemplate) http.HandleFunc("/", serveTemplate)
http.HandleFunc("/login", loginHandler) http.HandleFunc("/login", loginHandler)
http.HandleFunc("/reset_password", resetPasswordHandler) http.HandleFunc("/reset_password", resetPasswordHandler)
http.HandleFunc("/set_password", setPasswordHandler) http.HandleFunc("/set_password", setPasswordHandler)
http.HandleFunc("/logout", logoutHandler) http.HandleFunc("/logout", logoutHandler)
http.HandleFunc("/confirm", confirmHandler) http.HandleFunc("/confirm", confirmHandler)
http.HandleFunc("/metrics", metricsHandler) http.HandleFunc("/metrics", metricsHandler)
http.HandleFunc("/lastmetrics", lastmetricsHandler) http.HandleFunc("/lastmetrics", lastmetricsHandler)
http.HandleFunc("/save_scale_settings", save_scale_settingsHandler) http.HandleFunc("/save_scale_settings", save_scale_settingsHandler)
http.HandleFunc("/getstripepaymentintent", getstripepaymentintentHandler) http.HandleFunc("/getstripepaymentintent", getstripepaymentintentHandler)
http.HandleFunc("/stripewebhook", stripeWebhookHandler) http.HandleFunc("/stripewebhook", stripeWebhookHandler)
logit("Starting Web Application...") logit("Starting Web Application...")
http.ListenAndServe("127.0.0.1:4000", nil) http.ListenAndServe("127.0.0.1:4000", nil)

View File

@ -1,355 +1,354 @@
package main package main
import ( import (
"bytes" "bufio"
"fmt" "bytes"
"log" "fmt"
"net/http" "io/ioutil"
"time" "log"
"io/ioutil" "net/http"
"bufio" "strconv"
"strings" "strings"
"strconv" "time"
) )
type OneMetric struct { type OneMetric struct {
Deveui string Deveui string
Alias string Alias string
Alarmactive string Alarmactive string
Smsnumber string Smsnumber string
Timestamp string Timestamp string
Temperature string Temperature string
Humidity string Humidity string
Weight string Weight string
Weight_kg string Weight_kg string
Pressure string Pressure string
BatteryPercent string BatteryPercent string
ActiveUntil string ActiveUntil string
DaysUntilDeactivated int // berechneter Wert DaysUntilDeactivated int // berechneter Wert
} }
// metrics handler // metrics handler
func metricsHandler(response http.ResponseWriter, request *http.Request) { func metricsHandler(response http.ResponseWriter, request *http.Request) {
name := getUserName(request) name := getUserName(request)
if name != "" { if name != "" {
property, ok := request.URL.Query()["property"] property, ok := request.URL.Query()["property"]
if !ok || len(property[0]) < 1 { if !ok || len(property[0]) < 1 {
log.Println("Url Param 'property' is missing") log.Println("Url Param 'property' is missing")
fmt.Fprintf(response, "{ \"msg\": \"property must be specified in URL\" }") fmt.Fprintf(response, "{ \"msg\": \"property must be specified in URL\" }")
return return
} }
deveui, ok := request.URL.Query()["deveui"] deveui, ok := request.URL.Query()["deveui"]
if !ok || len(deveui[0]) < 1 { if !ok || len(deveui[0]) < 1 {
log.Println("Url Param 'deveui' is missing") log.Println("Url Param 'deveui' is missing")
fmt.Fprintf(response, "{ \"msg\": \"deveui must be specified in URL\" }") fmt.Fprintf(response, "{ \"msg\": \"deveui must be specified in URL\" }")
return return
} }
// Query()["deveui"] will return an array of items, // Query()["deveui"] will return an array of items,
// we only want the single item. // we only want the single item.
mydeveui := deveui[0] mydeveui := deveui[0]
if !(Contains(getMyDevs(name),mydeveui)) { if !(Contains(getMyDevs(name), mydeveui)) {
log.Println("specified 'deveui' does not belong to this user") log.Println("specified 'deveui' does not belong to this user")
fmt.Fprintf(response, "{ \"msg\": \"specified deveui does not belong to this user\" }") fmt.Fprintf(response, "{ \"msg\": \"specified deveui does not belong to this user\" }")
return return
} }
if AboExpired(mydeveui) { if AboExpired(mydeveui) {
log.Println("specified 'deveui' has an expired abo") log.Println("specified 'deveui' has an expired abo")
fmt.Fprintf(response, "{ \"msg\": \"specified deveui has an expired abo\" }") fmt.Fprintf(response, "{ \"msg\": \"specified deveui has an expired abo\" }")
return return
} }
log.Println("Url Param 'deveui' is: " + string(mydeveui)) log.Println("Url Param 'deveui' is: " + string(mydeveui))
// Format of start and stop: YYYY-MM-DDTHH:MI:SSZ // Format of start and stop: YYYY-MM-DDTHH:MI:SSZ
stop, ok := request.URL.Query()["stop"] stop, ok := request.URL.Query()["stop"]
var mystop string var mystop string
if !ok || len(stop[0]) < 1 { if !ok || len(stop[0]) < 1 {
log.Println("Url Param 'stop' is missing, set it to now") log.Println("Url Param 'stop' is missing, set it to now")
mystop = time.Now().Format("2006-01-02T15:04:05Z") mystop = time.Now().Format("2006-01-02T15:04:05Z")
} }
if ok { if ok {
mystop = stop[0] mystop = stop[0]
} }
layout := "2006-01-02T15:04:05Z" layout := "2006-01-02T15:04:05Z"
stopDate, err := time.Parse(layout, mystop) stopDate, err := time.Parse(layout, mystop)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
start, ok := request.URL.Query()["start"] start, ok := request.URL.Query()["start"]
var mystart string var mystart string
if !ok || len(start[0]) < 1 { if !ok || len(start[0]) < 1 {
log.Println("Url Param 'start' is missing, set it to stop minus one day") log.Println("Url Param 'start' is missing, set it to stop minus one day")
t := stopDate.AddDate(0,0,-1) t := stopDate.AddDate(0, 0, -1)
mystart = t.Format("2006-01-02T15:04:05Z") mystart = t.Format("2006-01-02T15:04:05Z")
} }
if ok { if ok {
mystart = start[0] mystart = start[0]
} }
url := "http://localhost:9999/api/v2/query?org=beieliorg" url := "http://localhost:9999/api/v2/query?org=beieliorg"
data := []byte(fmt.Sprintf(`from(bucket:"beielibucket") |> range(start: %s, stop: %s) |> filter(fn: (r) => r._measurement == "measurement") |> filter(fn: (r) => r._field == "%s") |> filter(fn: (r) => r.deveui == "%s")`,mystart,mystop,property[0],mydeveui)) data := []byte(fmt.Sprintf(`from(bucket:"beielibucket") |> range(start: %s, stop: %s) |> filter(fn: (r) => r._measurement == "measurement") |> filter(fn: (r) => r._field == "%s") |> filter(fn: (r) => r.deveui == "%s")`, mystart, mystop, property[0], mydeveui))
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data)) req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
if err != nil { if err != nil {
log.Fatal("Error reading request. ", err) log.Fatal("Error reading request. ", err)
} }
// Set headers // Set headers
req.Header.Set("Authorization", "Token OzSltiHLmm3WCaFPI0DrK0VFAVCiqcORNrGsgHO43jb0qodyVGAumJQ3HRtkaze53BVR3AmHqfkmrwrjq-xTyA==") req.Header.Set("Authorization", "Token OzSltiHLmm3WCaFPI0DrK0VFAVCiqcORNrGsgHO43jb0qodyVGAumJQ3HRtkaze53BVR3AmHqfkmrwrjq-xTyA==")
req.Header.Set("accept", "application/csv") req.Header.Set("accept", "application/csv")
req.Header.Set("content-type", "application/vnd.flux") req.Header.Set("content-type", "application/vnd.flux")
// Set client timeout // Set client timeout
client := &http.Client{Timeout: time.Second * 10} client := &http.Client{Timeout: time.Second * 10}
// Send request // Send request
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
log.Fatal("Error reading response. ", err) log.Fatal("Error reading response. ", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
fmt.Println("response Status:", resp.Status) fmt.Println("response Status:", resp.Status)
fmt.Println("response Headers:", resp.Header) fmt.Println("response Headers:", resp.Header)
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Fatal("Error reading body. ", err) log.Fatal("Error reading body. ", err)
} }
fmt.Fprintf(response,"[\n") fmt.Fprintf(response, "[\n")
scanner := bufio.NewScanner(strings.NewReader(string(body))) scanner := bufio.NewScanner(strings.NewReader(string(body)))
first := true first := true
for scanner.Scan() { for scanner.Scan() {
s := strings.Split(scanner.Text(),",") s := strings.Split(scanner.Text(), ",")
if ((len(s) >= 7) && !(strings.HasPrefix(s[5],"_"))) { if (len(s) >= 7) && !(strings.HasPrefix(s[5], "_")) {
t,err := time.Parse(time.RFC3339,s[5]) t, err := time.Parse(time.RFC3339, s[5])
if err != nil { if err != nil {
continue continue
} }
a := t.Unix() a := t.Unix()
b := s[6] b := s[6]
if !(first) { if !(first) {
fmt.Fprintf(response,",") fmt.Fprintf(response, ",")
} else { } else {
first = false first = false
} }
fmt.Fprintf(response,"[%d000,%s]\n",a,b) fmt.Fprintf(response, "[%d000,%s]\n", a, b)
} }
} }
fmt.Fprintf(response,"]\n") fmt.Fprintf(response, "]\n")
} else { } else {
fmt.Fprintf(response, "{ \"msg\": \"Only available for logged in users\" }") fmt.Fprintf(response, "{ \"msg\": \"Only available for logged in users\" }")
} }
} }
func lastmetricsHandler(response http.ResponseWriter, request *http.Request) { func lastmetricsHandler(response http.ResponseWriter, request *http.Request) {
name := getUserName(request) name := getUserName(request)
if name != "" { if name != "" {
deveui, ok := request.URL.Query()["deveui"] deveui, ok := request.URL.Query()["deveui"]
if !ok || len(deveui[0]) < 1 { if !ok || len(deveui[0]) < 1 {
log.Println("Url Param 'deveui' is missing") log.Println("Url Param 'deveui' is missing")
fmt.Fprintf(response, "{ \"msg\": \"deveui must be specified in URL\" }") fmt.Fprintf(response, "{ \"msg\": \"deveui must be specified in URL\" }")
return return
} }
// Query()["deveui"] will return an array of items, // Query()["deveui"] will return an array of items,
// we only want the single item. // we only want the single item.
mydeveui := deveui[0] mydeveui := deveui[0]
if !(Contains(getMyDevs(name),mydeveui)) { if !(Contains(getMyDevs(name), mydeveui)) {
log.Println("specified 'deveui' does not belong to this user") log.Println("specified 'deveui' does not belong to this user")
fmt.Fprintf(response, "{ \"msg\": \"specified deveui does not belong to this user\" }") fmt.Fprintf(response, "{ \"msg\": \"specified deveui does not belong to this user\" }")
return return
} }
log.Println("Url Param 'deveui' is: " + string(mydeveui)) log.Println("Url Param 'deveui' is: " + string(mydeveui))
url := "http://localhost:9999/api/v2/query?org=beieliorg" url := "http://localhost:9999/api/v2/query?org=beieliorg"
//data := []byte(fmt.Sprintf(`from(bucket:"beielibucket") |> range(start:-365d) |> filter(fn: (r) => r.deveui == "%s") |> filter(fn: (r) => r._field == "v" or r._field == "t") |> last() |> yield(name: "last")`,mydeveui)) //data := []byte(fmt.Sprintf(`from(bucket:"beielibucket") |> range(start:-365d) |> filter(fn: (r) => r.deveui == "%s") |> filter(fn: (r) => r._field == "v" or r._field == "t") |> last() |> yield(name: "last")`,mydeveui))
data := []byte(fmt.Sprintf(`from(bucket:"beielibucket") data := []byte(fmt.Sprintf(`from(bucket:"beielibucket")
|> range(start:-365d) |> range(start:-365d)
|> filter(fn: (r) => r.deveui == "%s") |> filter(fn: (r) => r.deveui == "%s")
|> filter(fn: (r) => r._field == "t" or r._field == "h" or r._field == "w" or r._field == "p" or r._field == "vp") |> filter(fn: (r) => r._field == "t" or r._field == "h" or r._field == "w" or r._field == "p" or r._field == "vp")
|> last() |> yield(name: "last")`,mydeveui)) |> last() |> yield(name: "last")`, mydeveui))
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data)) req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
if err != nil { if err != nil {
log.Fatal("Error reading request. ", err) log.Fatal("Error reading request. ", err)
} }
// Set headers // Set headers
req.Header.Set("Authorization", "Token OzSltiHLmm3WCaFPI0DrK0VFAVCiqcORNrGsgHO43jb0qodyVGAumJQ3HRtkaze53BVR3AmHqfkmrwrjq-xTyA==") req.Header.Set("Authorization", "Token OzSltiHLmm3WCaFPI0DrK0VFAVCiqcORNrGsgHO43jb0qodyVGAumJQ3HRtkaze53BVR3AmHqfkmrwrjq-xTyA==")
req.Header.Set("accept", "application/csv") req.Header.Set("accept", "application/csv")
req.Header.Set("content-type", "application/vnd.flux") req.Header.Set("content-type", "application/vnd.flux")
// Set client timeout // Set client timeout
client := &http.Client{Timeout: time.Second * 10} client := &http.Client{Timeout: time.Second * 10}
// Send request // Send request
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
log.Fatal("Error reading response. ", err) log.Fatal("Error reading response. ", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
fmt.Println("response Status:", resp.Status) fmt.Println("response Status:", resp.Status)
fmt.Println("response Headers:", resp.Header) fmt.Println("response Headers:", resp.Header)
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Fatal("Error reading body. ", err) log.Fatal("Error reading body. ", err)
} }
fmt.Println("response Body:", string(body)) fmt.Println("response Body:", string(body))
scanner := bufio.NewScanner(strings.NewReader(string(body))) scanner := bufio.NewScanner(strings.NewReader(string(body)))
ts := "" ts := ""
t := "" t := ""
h := "" h := ""
w := "" w := ""
p := "" p := ""
vp := "" vp := ""
location, err := time.LoadLocation("Europe/Zurich") location, err := time.LoadLocation("Europe/Zurich")
for scanner.Scan() { for scanner.Scan() {
s := strings.Split(scanner.Text(),",") s := strings.Split(scanner.Text(), ",")
if ((len(s) >= 7) && !(strings.HasPrefix(s[5],"_"))) { if (len(s) >= 7) && !(strings.HasPrefix(s[5], "_")) {
mytime,err := time.Parse(time.RFC3339,s[5]) mytime, err := time.Parse(time.RFC3339, s[5])
if err != nil { if err != nil {
continue continue
} }
ts = mytime.In(location).Format("02.01.2006 15:04") ts = mytime.In(location).Format("02.01.2006 15:04")
value := s[6] value := s[6]
field := s[7] field := s[7]
if field == "t" { if field == "t" {
t = value t = value
} else if field == "h" { } else if field == "h" {
h = value h = value
} else if field == "w" { } else if field == "w" {
w = value w = value
} else if field == "p" { } else if field == "p" {
p = value p = value
} else if field == "vp" { } else if field == "vp" {
vp = value vp = value
} }
} }
} }
fmt.Fprintf(response,`{ fmt.Fprintf(response, `{
"ts": "%s", "ts": "%s",
"t": "%s", "t": "%s",
"h": "%s", "h": "%s",
"w": "%s", "w": "%s",
"p": "%s", "p": "%s",
"vp": "%s" "vp": "%s"
}`,ts,t,h,w,p,vp) }`, ts, t, h, w, p, vp)
} else { } else {
fmt.Fprintf(response, "{ \"msg\": \"Only available for logged in users\" }") fmt.Fprintf(response, "{ \"msg\": \"Only available for logged in users\" }")
} }
} }
func CalcDaysUntil(mydate string) int { func CalcDaysUntil(mydate string) int {
var days int var days int
layout := "02.01.2006" layout := "02.01.2006"
t, err := time.Parse(layout, mydate) t, err := time.Parse(layout, mydate)
if err != nil { if err != nil {
days = 0 days = 0
} }
days = int(t.Sub(time.Now()).Hours() / 24) days = int(t.Sub(time.Now()).Hours() / 24)
return days return days
} }
func getLastMetrics(deveui string) OneMetric { func getLastMetrics(deveui string) OneMetric {
var res OneMetric var res OneMetric
url := "http://localhost:9999/api/v2/query?org=beieliorg" url := "http://localhost:9999/api/v2/query?org=beieliorg"
data := []byte(fmt.Sprintf(`from(bucket:"beielibucket") data := []byte(fmt.Sprintf(`from(bucket:"beielibucket")
|> range(start:-365d) |> range(start:-365d)
|> filter(fn: (r) => r.deveui == "%s") |> filter(fn: (r) => r.deveui == "%s")
|> filter(fn: (r) => r._field == "t" or r._field == "h" or r._field == "w" or r._field == "p" or r._field == "vp") |> filter(fn: (r) => r._field == "t" or r._field == "h" or r._field == "w" or r._field == "p" or r._field == "vp")
|> last() |> yield(name: "last")`,deveui)) |> last() |> yield(name: "last")`, deveui))
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data)) req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
if err != nil { if err != nil {
log.Fatal("Error reading request. ", err) log.Fatal("Error reading request. ", err)
} }
// Set headers // Set headers
req.Header.Set("Authorization", "Token OzSltiHLmm3WCaFPI0DrK0VFAVCiqcORNrGsgHO43jb0qodyVGAumJQ3HRtkaze53BVR3AmHqfkmrwrjq-xTyA==") req.Header.Set("Authorization", "Token OzSltiHLmm3WCaFPI0DrK0VFAVCiqcORNrGsgHO43jb0qodyVGAumJQ3HRtkaze53BVR3AmHqfkmrwrjq-xTyA==")
req.Header.Set("accept", "application/csv") req.Header.Set("accept", "application/csv")
req.Header.Set("content-type", "application/vnd.flux") req.Header.Set("content-type", "application/vnd.flux")
// Set client timeout // Set client timeout
client := &http.Client{Timeout: time.Second * 10} client := &http.Client{Timeout: time.Second * 10}
// Send request // Send request
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
log.Fatal("Error reading response. ", err) log.Fatal("Error reading response. ", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
fmt.Println("response Status:", resp.Status) fmt.Println("response Status:", resp.Status)
fmt.Println("response Headers:", resp.Header) fmt.Println("response Headers:", resp.Header)
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Fatal("Error reading body. ", err) log.Fatal("Error reading body. ", err)
} }
fmt.Println("response Body:", string(body)) fmt.Println("response Body:", string(body))
scanner := bufio.NewScanner(strings.NewReader(string(body))) scanner := bufio.NewScanner(strings.NewReader(string(body)))
location, err := time.LoadLocation("Europe/Zurich") location, err := time.LoadLocation("Europe/Zurich")
for scanner.Scan() { for scanner.Scan() {
s := strings.Split(scanner.Text(),",") s := strings.Split(scanner.Text(), ",")
if ((len(s) >= 7) && !(strings.HasPrefix(s[5],"_"))) { if (len(s) >= 7) && !(strings.HasPrefix(s[5], "_")) {
mytime,err := time.Parse(time.RFC3339,s[5]) mytime, err := time.Parse(time.RFC3339, s[5])
if err != nil { if err != nil {
continue continue
} }
res.Timestamp = mytime.In(location).Format("02.01.2006 15:04") res.Timestamp = mytime.In(location).Format("02.01.2006 15:04")
value := s[6] value := s[6]
field := s[7] field := s[7]
if field == "t" { if field == "t" {
res.Temperature = value res.Temperature = value
} else if field == "h" { } else if field == "h" {
res.Humidity = value res.Humidity = value
} else if field == "w" { } else if field == "w" {
res.Weight = value res.Weight = value
i, err := strconv.Atoi(value) i, err := strconv.Atoi(value)
if (err == nil) { if err == nil {
res.Weight_kg = fmt.Sprintf("%.2f",float64(i) / 1000.0) res.Weight_kg = fmt.Sprintf("%.2f", float64(i)/1000.0)
} else { } else {
res.Weight_kg = "ERR" res.Weight_kg = "ERR"
} }
} else if field == "p" { } else if field == "p" {
res.Pressure = value res.Pressure = value
} else if field == "vp" { } else if field == "vp" {
res.BatteryPercent = value res.BatteryPercent = value
} }
} }
} }
res.Deveui = deveui res.Deveui = deveui
res.Alias = getDevAlias(deveui) res.Alias = getDevAlias(deveui)
res.Alarmactive = getDevAlarmactive(deveui) res.Alarmactive = getDevAlarmactive(deveui)
res.Smsnumber = getDevSmsnumber(deveui) res.Smsnumber = getDevSmsnumber(deveui)
res.ActiveUntil = getActiveUntil(deveui) res.ActiveUntil = getActiveUntil(deveui)
res.DaysUntilDeactivated = CalcDaysUntil(res.ActiveUntil) res.DaysUntilDeactivated = CalcDaysUntil(res.ActiveUntil)
return res return res
} }

View File

@ -1,13 +1,13 @@
package main package main
import ( import (
"time"
"strings"
"fmt"
"log"
"crypto/rand" "crypto/rand"
"fmt"
"github.com/gomodule/redigo/redis"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"github.com/gomodule/redigo/redis" "log"
"strings"
"time"
) )
var globalPool *redis.Pool var globalPool *redis.Pool
@ -44,18 +44,18 @@ func ping(c redis.Conn) error {
return err return err
} }
logit("PING Response = "+s) logit("PING Response = " + s)
// Output: PONG // Output: PONG
return nil return nil
} }
type Dev struct { type Dev struct {
Deveui string Deveui string
Alias string Alias string
Alarmactive string Alarmactive string
Smsnumber string Smsnumber string
ActiveUntil string // Abo bezahlt bis TT.MM.YYYY ActiveUntil string // Abo bezahlt bis TT.MM.YYYY
} }
func initDB() { func initDB() {
@ -64,17 +64,17 @@ func initDB() {
pool := newPool() pool := newPool()
// get a connection from the globalPool (redis.Conn) // get a connection from the globalPool (redis.Conn)
conn := pool.Get() conn := pool.Get()
defer conn.Close() defer conn.Close()
globalPool = pool globalPool = pool
// wir machen einen Connection Test // wir machen einen Connection Test
ping(conn) ping(conn)
// Wir legen einen initialen Admin User an, falls es diesen noch nicht gibt // Wir legen einen initialen Admin User an, falls es diesen noch nicht gibt
if checkUserAvailable("joerg.lehmann@nbit.ch") { if checkUserAvailable("joerg.lehmann@nbit.ch") {
insertUser("joerg.lehmann@nbit.ch","changeme123","Y"); insertUser("joerg.lehmann@nbit.ch", "changeme123", "Y")
} }
} }
@ -82,10 +82,9 @@ func closeDB() {
globalPool.Close() globalPool.Close()
} }
func updateScaleSettings(scaleSettings Dev) error { func updateScaleSettings(scaleSettings Dev) error {
conn := globalPool.Get() conn := globalPool.Get()
defer conn.Close() defer conn.Close()
// SET object // SET object
_, err := conn.Do("HMSET", devPrefix+scaleSettings.Deveui, "alias", scaleSettings.Alias, "alarmactive", scaleSettings.Alarmactive, "smsnumber", scaleSettings.Smsnumber) _, err := conn.Do("HMSET", devPrefix+scaleSettings.Deveui, "alias", scaleSettings.Alias, "alarmactive", scaleSettings.Alarmactive, "smsnumber", scaleSettings.Smsnumber)
@ -96,301 +95,294 @@ func updateScaleSettings(scaleSettings Dev) error {
return nil return nil
} }
func checkUserAvailable(username string) bool { func checkUserAvailable(username string) bool {
logit("checkUserAvailable: User: "+username) logit("checkUserAvailable: User: " + username)
conn := globalPool.Get() conn := globalPool.Get()
defer conn.Close() defer conn.Close()
_, err := redis.String(conn.Do("GET", userPrefix+username)) _, err := redis.String(conn.Do("GET", userPrefix+username))
if (err == redis.ErrNil) { if err == redis.ErrNil {
logit("User does not exist and is therefore available:"+username) logit("User does not exist and is therefore available:" + username)
return true return true
} else if err != nil { } else if err != nil {
logit("checkUserAvailable: Error to query Key Value Store") logit("checkUserAvailable: Error to query Key Value Store")
return false return false
} }
return false return false
} }
func getMyDevs(username string) []string { func getMyDevs(username string) []string {
res := []string{} res := []string{}
if username == "" { if username == "" {
return res return res
} }
conn := globalPool.Get()
defer conn.Close()
conn := globalPool.Get() logit("getMyDevs: User: " + username)
defer conn.Close()
logit("getMyDevs: User: "+username)
mydevs, err := redis.String(conn.Do("HGET", userPrefix+username, "my_devs")) mydevs, err := redis.String(conn.Do("HGET", userPrefix+username, "my_devs"))
if err == nil { if err == nil {
logit("getMyDevs: mydevs: "+mydevs) logit("getMyDevs: mydevs: " + mydevs)
res = strings.Split(mydevs, ",") res = strings.Split(mydevs, ",")
} else { } else {
log.Print(err) log.Print(err)
} }
return res return res
} }
func getDevAlias(deveui string) string { func getDevAlias(deveui string) string {
res := deveui res := deveui
if deveui == "" { if deveui == "" {
return res return res
} }
conn := globalPool.Get()
defer conn.Close()
conn := globalPool.Get() logit("getDevAlias: Deveui: " + deveui)
defer conn.Close()
logit("getDevAlias: Deveui: "+deveui)
alias, err := redis.String(conn.Do("HGET", devPrefix+deveui, "alias")) alias, err := redis.String(conn.Do("HGET", devPrefix+deveui, "alias"))
if err == nil { if err == nil {
logit("getDevAlias: alias: "+alias) logit("getDevAlias: alias: " + alias)
res = alias res = alias
} else { } else {
log.Print(err) log.Print(err)
} }
return res return res
} }
func getDevAlarmactive(deveui string) string { func getDevAlarmactive(deveui string) string {
res := "0" res := "0"
if deveui == "" { if deveui == "" {
return res return res
} }
conn := globalPool.Get()
defer conn.Close()
conn := globalPool.Get() logit("getDevAlarmactive: Deveui: " + deveui)
defer conn.Close()
logit("getDevAlarmactive: Deveui: "+deveui)
alarmactive, err := redis.String(conn.Do("HGET", devPrefix+deveui, "alarmactive")) alarmactive, err := redis.String(conn.Do("HGET", devPrefix+deveui, "alarmactive"))
if err == nil { if err == nil {
logit("getDevAlarmactive: alarmactive: "+alarmactive) logit("getDevAlarmactive: alarmactive: " + alarmactive)
res = alarmactive res = alarmactive
} else { } else {
log.Print(err) log.Print(err)
} }
return res return res
} }
func getDevSmsnumber(deveui string) string { func getDevSmsnumber(deveui string) string {
res := "+4179XXXXXXX" res := "+4179XXXXXXX"
if deveui == "" { if deveui == "" {
return res return res
} }
conn := globalPool.Get()
defer conn.Close()
conn := globalPool.Get() logit("getDevSmsnumber: Deveui: " + deveui)
defer conn.Close()
logit("getDevSmsnumber: Deveui: "+deveui)
smsnumber, err := redis.String(conn.Do("HGET", devPrefix+deveui, "smsnumber")) smsnumber, err := redis.String(conn.Do("HGET", devPrefix+deveui, "smsnumber"))
if err == nil { if err == nil {
logit("getDevAlarmactive: smsnumber: "+smsnumber) logit("getDevAlarmactive: smsnumber: " + smsnumber)
res = smsnumber res = smsnumber
} else { } else {
log.Print(err) log.Print(err)
} }
return res return res
} }
func getActiveUntil(deveui string) string { func getActiveUntil(deveui string) string {
res := "" res := ""
if deveui == "" { if deveui == "" {
return res return res
} }
conn := globalPool.Get()
defer conn.Close()
conn := globalPool.Get() logit("getActiveUntil: Deveui: " + deveui)
defer conn.Close()
logit("getActiveUntil: Deveui: "+deveui)
activeuntil, err := redis.String(conn.Do("HGET", devPrefix+deveui, "active_until")) activeuntil, err := redis.String(conn.Do("HGET", devPrefix+deveui, "active_until"))
if err == nil { if err == nil {
logit("getActiveUntil: activeuntil: "+activeuntil) logit("getActiveUntil: activeuntil: " + activeuntil)
res = activeuntil res = activeuntil
} else { } else {
log.Print(err) log.Print(err)
} }
return res return res
} }
func AboExpired(deveui string) bool { func AboExpired(deveui string) bool {
active_until := getActiveUntil(deveui); active_until := getActiveUntil(deveui)
layout := "02.01.2006" layout := "02.01.2006"
t, _ := time.Parse(layout, active_until) t, _ := time.Parse(layout, active_until)
return t.Before(time.Now()) return t.Before(time.Now())
} }
func prolongActivation(deveui string, years int) (string, error) { func prolongActivation(deveui string, years int) (string, error) {
conn := globalPool.Get() conn := globalPool.Get()
defer conn.Close() defer conn.Close()
active_until_old, err := redis.String(conn.Do("HGET", devPrefix+deveui, "active_until")) active_until_old, err := redis.String(conn.Do("HGET", devPrefix+deveui, "active_until"))
if err == nil { if err == nil {
logit("prolongActivation: active_until: " +active_until_old) logit("prolongActivation: active_until: " + active_until_old)
} else { } else {
log.Print(err) log.Print(err)
} }
layout := "02.01.2006" layout := "02.01.2006"
t, err := time.Parse(layout, active_until_old) t, err := time.Parse(layout, active_until_old)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(t.Unix()) fmt.Println(t.Unix())
var t_new time.Time var t_new time.Time
if t.Before(time.Now()) { if t.Before(time.Now()) {
t_new = time.Now().AddDate(years, 0, 0) t_new = time.Now().AddDate(years, 0, 0)
} else { } else {
t_new = t.AddDate(years, 0, 0) t_new = t.AddDate(years, 0, 0)
} }
active_until_new := t_new.Format(layout) active_until_new := t_new.Format(layout)
// SET object // SET object
_, err1 := conn.Do("HMSET", devPrefix+deveui, "active_until", active_until_new) _, err1 := conn.Do("HMSET", devPrefix+deveui, "active_until", active_until_new)
if err1 != nil { if err1 != nil {
return "",err1 return "", err1
} }
return active_until_new, nil return active_until_new, nil
} }
func randString(n int) string { func randString(n int) string {
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
var bytes = make([]byte, n) var bytes = make([]byte, n)
rand.Read(bytes) rand.Read(bytes)
for i, b := range bytes { for i, b := range bytes {
bytes[i] = alphanum[b % byte(len(alphanum))] bytes[i] = alphanum[b%byte(len(alphanum))]
} }
return string(bytes) return string(bytes)
} }
func insertUser(username,password,is_admin string) { func insertUser(username, password, is_admin string) {
conn := globalPool.Get() conn := globalPool.Get()
defer conn.Close() defer conn.Close()
logit("insertUser: "+username) logit("insertUser: " + username)
pwd := []byte(password) pwd := []byte(password)
hashedPassword,err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost) hashedPassword, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost)
if err != nil { if err != nil {
logit("insertUser: Error with bcrypt.GenerateFromPassword, User: "+username) logit("insertUser: Error with bcrypt.GenerateFromPassword, User: " + username)
return return
} }
confirm_id := "" confirm_id := ""
_, err = conn.Do("HMSET", userPrefix+username, "password", string(hashedPassword), "new_password", string(hashedPassword), "confirm_id", confirm_id, "last_login", "", "my_devs","") _, err = conn.Do("HMSET", userPrefix+username, "password", string(hashedPassword), "new_password", string(hashedPassword), "confirm_id", confirm_id, "last_login", "", "my_devs", "")
if err != nil { if err != nil {
logit("insertUser: Error inserting User: "+username) logit("insertUser: Error inserting User: " + username)
return return
} }
} }
func updateUser(username,password string) { func updateUser(username, password string) {
conn := globalPool.Get() conn := globalPool.Get()
defer conn.Close() defer conn.Close()
logit("updateUser: "+username) logit("updateUser: " + username)
pwd := []byte(password) pwd := []byte(password)
hashedPassword,err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost) hashedPassword, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost)
if err != nil { if err != nil {
logit("updateUser: Error with bcrypt.GenerateFromPassword, User: "+username) logit("updateUser: Error with bcrypt.GenerateFromPassword, User: " + username)
return return
} }
confirm_id := randString(30) confirm_id := randString(30)
_, err = conn.Do("HMSET", userPrefix+username, "new_password", string(hashedPassword), "confirm_id", confirm_id) _, err = conn.Do("HMSET", userPrefix+username, "new_password", string(hashedPassword), "confirm_id", confirm_id)
if err != nil { if err != nil {
logit("updateUser: Error updateing User: "+username) logit("updateUser: Error updateing User: " + username)
return return
} }
_, err = conn.Do("SET", confirmPrefix+confirm_id,username) _, err = conn.Do("SET", confirmPrefix+confirm_id, username)
if err != nil { if err != nil {
logit("updateUser: Error inserting confirm_id: "+confirm_id+": "+username) logit("updateUser: Error inserting confirm_id: " + confirm_id + ": " + username)
return return
} }
sendEmail(username,confirm_id) sendEmail(username, confirm_id)
} }
func checkLoginCredentials(username,password string) bool { func checkLoginCredentials(username, password string) bool {
conn := globalPool.Get() conn := globalPool.Get()
defer conn.Close() defer conn.Close()
logit("checkLoginCredentials: called with username,password: "+username+","+password) logit("checkLoginCredentials: called with username,password: " + username + "," + password)
pwd, err := redis.String(conn.Do("HGET", userPrefix+username, "password")) pwd, err := redis.String(conn.Do("HGET", userPrefix+username, "password"))
if err == nil { if err == nil {
logit("checkLoginCredentials: pwd: "+pwd+" CMD: HGET "+userPrefix+username+userPrefix+username+" confirm_id") logit("checkLoginCredentials: pwd: " + pwd + " CMD: HGET " + userPrefix + username + userPrefix + username + " confirm_id")
cid, err := redis.String(conn.Do("HGET", userPrefix+username, "confirm_id")) cid, err := redis.String(conn.Do("HGET", userPrefix+username, "confirm_id"))
if err == nil { if err == nil {
logit("checkLoginCredentials: cid: "+cid) logit("checkLoginCredentials: cid: " + cid)
if !(err != nil && cid != "") { if !(err != nil && cid != "") {
logit("checkLoginCredentials: pwd: "+pwd) logit("checkLoginCredentials: pwd: " + pwd)
if err != nil { if err != nil {
return false return false
} }
} }
} }
} else { } else {
log.Print(err) log.Print(err)
return false return false
} }
hashedPassword := []byte(pwd) hashedPassword := []byte(pwd)
err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(password)) err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(password))
return err == nil return err == nil
} }
func updateLoginTime(username string) { func updateLoginTime(username string) {
conn := globalPool.Get() conn := globalPool.Get()
defer conn.Close() defer conn.Close()
_, err := conn.Do("HSET", userPrefix+username, "last_login", time.Now().UTC().Format("2006-01-02 15:04:05")) _, err := conn.Do("HSET", userPrefix+username, "last_login", time.Now().UTC().Format("2006-01-02 15:04:05"))
if err != nil { if err != nil {
logit("updateUser: Error updateing User: "+username) logit("updateUser: Error updateing User: " + username)
return return
} }
} }
func confirmUser(confirm_id string) { func confirmUser(confirm_id string) {
conn := globalPool.Get() conn := globalPool.Get()
defer conn.Close() defer conn.Close()
u, err := redis.String(conn.Do("GET", confirmPrefix+confirm_id)) u, err := redis.String(conn.Do("GET", confirmPrefix+confirm_id))
if err != nil { if err != nil {
logit("confirmUser: Error with searching confirm_id: "+confirm_id) logit("confirmUser: Error with searching confirm_id: " + confirm_id)
return return
} }
new_password, err := redis.String(conn.Do("HGET", userPrefix+u, "new_password")) new_password, err := redis.String(conn.Do("HGET", userPrefix+u, "new_password"))
if err != nil { if err != nil {
logit("confirmUser: Error with getting new_password: "+u) logit("confirmUser: Error with getting new_password: " + u)
return return
} }
_, err = conn.Do("HMSET", userPrefix+u, "confirm_id", "", "password", new_password) _, err = conn.Do("HMSET", userPrefix+u, "confirm_id", "", "password", new_password)
if err != nil { if err != nil {
logit("confirmUser: Error updateing User: "+u) logit("confirmUser: Error updateing User: " + u)
return return
} }
_, err = conn.Do("DEL", confirmPrefix+confirm_id) _, err = conn.Do("DEL", confirmPrefix+confirm_id)
if err != nil { if err != nil {
logit("confirmUser: Error deleting confirm_id: "+confirm_id) logit("confirmUser: Error deleting confirm_id: " + confirm_id)
return return
} }
} }

164
scales.go
View File

@ -1,109 +1,109 @@
package main package main
import ( import (
"fmt" "fmt"
"log" "log"
"regexp" "net/http"
"net/http" "regexp"
) )
// scales handler // scales handler
func save_scale_settingsHandler(response http.ResponseWriter, request *http.Request) { func save_scale_settingsHandler(response http.ResponseWriter, request *http.Request) {
name := getUserName(request) name := getUserName(request)
if name != "" { if name != "" {
deveui, ok := request.URL.Query()["deveui"] deveui, ok := request.URL.Query()["deveui"]
if !ok || len(deveui[0]) < 1 { if !ok || len(deveui[0]) < 1 {
log.Println("Url Param 'deveui' is missing") log.Println("Url Param 'deveui' is missing")
fmt.Fprintf(response, "{ \"rc\": 1, \"msg\": \"deveui must be specified in URL\" }") fmt.Fprintf(response, "{ \"rc\": 1, \"msg\": \"deveui must be specified in URL\" }")
return return
} }
// Query()["deveui"] will return an array of items, // Query()["deveui"] will return an array of items,
// we only want the single item. // we only want the single item.
mydeveui := deveui[0] mydeveui := deveui[0]
if (len(mydeveui) != 16) { if len(mydeveui) != 16 {
log.Println("specified 'deveui' has invalid length") log.Println("specified 'deveui' has invalid length")
fmt.Fprintf(response, "{ \"rc\": 8, \"msg\": \"specified deveui has invalid length\" }") fmt.Fprintf(response, "{ \"rc\": 8, \"msg\": \"specified deveui has invalid length\" }")
return return
} }
if !(Contains(getMyDevs(name),mydeveui)) { if !(Contains(getMyDevs(name), mydeveui)) {
log.Println("specified 'deveui' does not belong to this user") log.Println("specified 'deveui' does not belong to this user")
fmt.Fprintf(response, "{ \"rc\": 2, \"msg\": \"specified deveui does not belong to this user\" }") fmt.Fprintf(response, "{ \"rc\": 2, \"msg\": \"specified deveui does not belong to this user\" }")
return return
} }
log.Println("Url Param 'deveui' is: " + string(mydeveui)) log.Println("Url Param 'deveui' is: " + string(mydeveui))
alias, ok2 := request.URL.Query()["alias"] alias, ok2 := request.URL.Query()["alias"]
if !ok2 || len(alias[0]) < 1 { if !ok2 || len(alias[0]) < 1 {
log.Println("Url Param 'alias' is missing") log.Println("Url Param 'alias' is missing")
fmt.Fprintf(response, "{ \"rc\": 3, \"msg\": \"alias must be specified in URL\" }") fmt.Fprintf(response, "{ \"rc\": 3, \"msg\": \"alias must be specified in URL\" }")
return return
} }
myalias := alias[0] myalias := alias[0]
// validate alias // validate alias
match, _ := regexp.MatchString("^[a-zA-Z0-9 ]{1,16}$", myalias) match, _ := regexp.MatchString("^[a-zA-Z0-9 ]{1,16}$", myalias)
if !(match) { if !(match) {
log.Println("Url Param 'alias' is not valid") log.Println("Url Param 'alias' is not valid")
fmt.Fprintf(response, "{ \"rc\": 9, \"msg\": \"alias is not valid\" }") fmt.Fprintf(response, "{ \"rc\": 9, \"msg\": \"alias is not valid\" }")
return return
} }
alarmactive, ok3 := request.URL.Query()["alarmactive"] alarmactive, ok3 := request.URL.Query()["alarmactive"]
if !ok3 || len(alarmactive[0]) < 1 { if !ok3 || len(alarmactive[0]) < 1 {
log.Println("Url Param 'alarmactive' is missing") log.Println("Url Param 'alarmactive' is missing")
fmt.Fprintf(response, "{ \"rc\": 4, \"msg\": \"alarmactive must be specified in URL\" }") fmt.Fprintf(response, "{ \"rc\": 4, \"msg\": \"alarmactive must be specified in URL\" }")
return return
} }
myalarmactive := alarmactive[0] myalarmactive := alarmactive[0]
if !((myalarmactive == "0") || (myalarmactive == "1")) { if !((myalarmactive == "0") || (myalarmactive == "1")) {
log.Println("Url Param 'alarmactive' is not valid") log.Println("Url Param 'alarmactive' is not valid")
fmt.Fprintf(response, "{ \"rc\": 10, \"msg\": \"alarmactive is not valid\" }") fmt.Fprintf(response, "{ \"rc\": 10, \"msg\": \"alarmactive is not valid\" }")
return return
} }
smsnumber, ok4 := request.URL.Query()["smsnumber"] smsnumber, ok4 := request.URL.Query()["smsnumber"]
if !ok4 || len(smsnumber[0]) < 1 { if !ok4 || len(smsnumber[0]) < 1 {
log.Println("Url Param 'smsnumber' is missing") log.Println("Url Param 'smsnumber' is missing")
fmt.Fprintf(response, "{ \"rc\": 5, \"msg\": \"smsnumber must be specified in URL\" }") fmt.Fprintf(response, "{ \"rc\": 5, \"msg\": \"smsnumber must be specified in URL\" }")
return return
} }
mysmsnumber := smsnumber[0] mysmsnumber := smsnumber[0]
match1, _ := regexp.MatchString(`^\+[0-9]{11,11}$`, mysmsnumber) match1, _ := regexp.MatchString(`^\+[0-9]{11,11}$`, mysmsnumber)
if !(match1) { if !(match1) {
log.Println("Url Param 'smsnumber' is not valid") log.Println("Url Param 'smsnumber' is not valid")
fmt.Fprintf(response, "{ \"rc\": 11, \"msg\": \"smsnumber is not valid, must be in in format +41791234567\" }") fmt.Fprintf(response, "{ \"rc\": 11, \"msg\": \"smsnumber is not valid, must be in in format +41791234567\" }")
return return
} }
var mydev Dev var mydev Dev
mydev.Deveui = mydeveui mydev.Deveui = mydeveui
mydev.Alias = myalias mydev.Alias = myalias
mydev.Alarmactive = myalarmactive mydev.Alarmactive = myalarmactive
mydev.Smsnumber = mysmsnumber mydev.Smsnumber = mysmsnumber
// now we try to save the settings // now we try to save the settings
err := updateScaleSettings(mydev) err := updateScaleSettings(mydev)
if err != nil { if err != nil {
log.Println("Error to Update Device Settings") log.Println("Error to Update Device Settings")
fmt.Fprintf(response, "{ \"rc\": 6, \"msg\": \"error with saving device settings\" }") fmt.Fprintf(response, "{ \"rc\": 6, \"msg\": \"error with saving device settings\" }")
return return
} else { } else {
fmt.Fprintf(response, "{ \"rc\": 0, \"msg\": \"SUCCESS\" }") fmt.Fprintf(response, "{ \"rc\": 0, \"msg\": \"SUCCESS\" }")
} }
} else { } else {
fmt.Fprintf(response, "{ \"rc\": 7, \"msg\": \"Only available for logged in users\" }") fmt.Fprintf(response, "{ \"rc\": 7, \"msg\": \"Only available for logged in users\" }")
} }
} }

190
stripe.go
View File

@ -1,119 +1,125 @@
package main package main
import ( import (
"fmt" "encoding/json"
"log" "fmt"
"os" "github.com/stripe/stripe-go"
"io/ioutil" "github.com/stripe/stripe-go/paymentintent"
"encoding/json" "io/ioutil"
"net/http" "log"
"strings" "net/http"
"strconv" "os"
"github.com/stripe/stripe-go" "strconv"
"github.com/stripe/stripe-go/paymentintent" "strings"
) )
func getStripeKey() string { func getStripeKey() string {
return "sk_test_GJbXPD0IAFNvvGpNEpaeDfhl" return "sk_test_GJbXPD0IAFNvvGpNEpaeDfhl"
} }
func getstripepaymentintentHandler(response http.ResponseWriter, request *http.Request) { func getstripepaymentintentHandler(response http.ResponseWriter, request *http.Request) {
name := getUserName(request) name := getUserName(request)
if name != "" { if name != "" {
charge_data, ok := request.URL.Query()["charge_data"] charge_data, ok := request.URL.Query()["charge_data"]
if !ok || len(charge_data[0]) < 1 { if !ok || len(charge_data[0]) < 1 {
log.Println("Url Param 'charge_data' is missing") log.Println("Url Param 'charge_data' is missing")
fmt.Fprintf(response, "{ \"rc\": 1, \"msg\": \"charge_data must be specified in URL\" }") fmt.Fprintf(response, "{ \"rc\": 1, \"msg\": \"charge_data must be specified in URL\" }")
return return
} }
scales := strings.Split(charge_data[0],",") scales := strings.Split(charge_data[0], ",")
var abo_years = 0 var abo_years = 0
var items []string var items []string
for _,scale := range scales { for _, scale := range scales {
items = strings.Split(scale,":") items = strings.Split(scale, ":")
if (len(items) == 2) { if len(items) == 2 {
abo_count, err := strconv.Atoi(items[1]) abo_count, err := strconv.Atoi(items[1])
if err == nil { if err == nil {
abo_years += abo_count abo_years += abo_count
} }
} }
} }
abo_amount := int64(abo_years * 2400) abo_amount := int64(abo_years * 2400)
stripe.Key = getStripeKey() stripe.Key = getStripeKey()
params := &stripe.PaymentIntentParams{ params := &stripe.PaymentIntentParams{
Amount: stripe.Int64(abo_amount), Amount: stripe.Int64(abo_amount),
Currency: stripe.String(string(stripe.CurrencyCHF)), Currency: stripe.String(string(stripe.CurrencyCHF)),
ReceiptEmail: stripe.String(name), ReceiptEmail: stripe.String(name),
} }
params.AddMetadata("charge_data", charge_data[0]) params.AddMetadata("charge_data", charge_data[0])
paymentintent, err := paymentintent.New(params) paymentintent, err := paymentintent.New(params)
if err != nil { if err != nil {
fmt.Fprintf(response,"{ \"rc\": 5, \"stripeclientsecret\": \"%s\" }\n",err) fmt.Fprintf(response, "{ \"rc\": 5, \"stripeclientsecret\": \"%s\" }\n", err)
} else { } else {
fmt.Fprintf(response,"{ \"rc\": 0, \"stripeclientsecret\": \"%s\" }\n",paymentintent.ClientSecret) fmt.Fprintf(response, "{ \"rc\": 0, \"stripeclientsecret\": \"%s\" }\n", paymentintent.ClientSecret)
} }
} else { } else {
fmt.Fprintf(response, "{ \"rc\": 6, \"msg\": \"Only available for logged in users\" }") fmt.Fprintf(response, "{ \"rc\": 6, \"msg\": \"Only available for logged in users\" }")
} }
} }
func HandlePayment(user string, charge_data string, amount int64) { func HandlePayment(user string, charge_data string, amount int64) {
fmt.Printf("HandlePayment for %s (charge_data: %s, amount: %d)!\n", user, charge_data, amount) fmt.Printf("HandlePayment for %s (charge_data: %s, amount: %d)!\n", user, charge_data, amount)
for _, token := range strings.Split(charge_data,",") { charge_data_email_text := fmt.Sprintf("%-30s %20s %10s\n", "Alias", "verlängern bis", "Betrag")
res := strings.Split(token,":") charge_data_email_text = charge_data_email_text + strings.Repeat("-", 62) + "\n"
if (len(res)) == 2 { for _, token := range strings.Split(charge_data, ",") {
deveui := res[0] res := strings.Split(token, ":")
years, _ := strconv.Atoi(res[1]) if (len(res)) == 2 {
fmt.Printf("prolongActivation %s: %d\n", deveui, years) deveui := res[0]
prolongActivation(deveui, years) years, _ := strconv.Atoi(res[1])
} fmt.Printf("prolongActivation %s: %d\n", deveui, years)
} prolongActivation(deveui, years)
sendPaymentConfirmationEmail(user,charge_data,amount) line := fmt.Sprintf("%-30s %20s %10.2f\n", getDevAlias(deveui), getActiveUntil(deveui), float64(24*years))
charge_data_email_text = charge_data_email_text + line
}
}
charge_data_email_text = charge_data_email_text + strings.Repeat("-", 62) + "\n"
charge_data_email_text = charge_data_email_text + fmt.Sprintf("%-30s %20s %10.2f\n", "Total CHF", "", float64(amount/100))
sendPaymentConfirmationEmail(user, charge_data_email_text, amount)
} }
func stripeWebhookHandler(w http.ResponseWriter, req *http.Request) { func stripeWebhookHandler(w http.ResponseWriter, req *http.Request) {
const MaxBodyBytes = int64(65536) const MaxBodyBytes = int64(65536)
req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes)
payload, err := ioutil.ReadAll(req.Body) payload, err := ioutil.ReadAll(req.Body)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err)
w.WriteHeader(http.StatusServiceUnavailable) w.WriteHeader(http.StatusServiceUnavailable)
return return
} }
event := stripe.Event{} event := stripe.Event{}
if err := json.Unmarshal(payload, &event); err != nil { if err := json.Unmarshal(payload, &event); err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse webhook body json: %v\n", err.Error()) fmt.Fprintf(os.Stderr, "Failed to parse webhook body json: %v\n", err.Error())
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
return return
} }
// Unmarshal the event data into an appropriate struct depending on its Type // Unmarshal the event data into an appropriate struct depending on its Type
switch event.Type { switch event.Type {
case "payment_intent.succeeded": case "payment_intent.succeeded":
var paymentIntent stripe.PaymentIntent var paymentIntent stripe.PaymentIntent
err := json.Unmarshal(event.Data.Raw, &paymentIntent) err := json.Unmarshal(event.Data.Raw, &paymentIntent)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err)
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
return return
} }
fmt.Printf("PaymentIntent was successful (charge_data: %s, amount: %d)!\n", paymentIntent.Metadata["charge_data"], paymentIntent.Amount) fmt.Printf("PaymentIntent was successful (charge_data: %s, amount: %d)!\n", paymentIntent.Metadata["charge_data"], paymentIntent.Amount)
HandlePayment(paymentIntent.ReceiptEmail, paymentIntent.Metadata["charge_data"], paymentIntent.Amount) HandlePayment(paymentIntent.ReceiptEmail, paymentIntent.Metadata["charge_data"], paymentIntent.Amount)
// ... handle other event types // ... handle other event types
default: default:
fmt.Fprintf(os.Stderr, "Unexpected event type: %s\n", event.Type) fmt.Fprintf(os.Stderr, "Unexpected event type: %s\n", event.Type)
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
return return
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }