diff --git a/apiV1EmailPass.go b/apiV1EmailPass.go new file mode 100644 index 0000000..974bcf0 --- /dev/null +++ b/apiV1EmailPass.go @@ -0,0 +1,80 @@ +package main + +import ( + "biukop.com/sfm/loan" + "fmt" + "github.com/brianvoe/gofakeit/v6" + log "github.com/sirupsen/logrus" + "net/http" + "net/smtp" + "strings" +) + +func apiV1EmailPassword(w http.ResponseWriter, r *http.Request, ss *loan.Session) { + id := r.URL.Path[len(apiV1Prefix+"email-password/"):] //remove prefix + u := loan.User{} + e := u.Read(id) + + if e != nil { + apiV1Client403Error(w, r, ss) + return + } + + newPass := gofakeit.Password(true, true, true, false, false, 8) + log.Info("newPass", u, newPass) + u.SetPass(newPass) + e = u.Write() + if e != nil { + apiV1Client403Error(w, r, ss) + return + } + sendEmailPassLink(u, u.Login, newPass) + apiV1SendJson(true, w, r, ss) +} + +func sendEmailPassLink(user loan.User, email string, pass string) { + // Sender data. + from := "mailer@biukop.com.au" + password := "hpfitsrujgkewcdw" + + // Receiver email address. + to := []string{ + "patrick@biukop.com.au", + email, + } + + // smtp server configuration. + smtpHost := "smtp.gmail.com" + smtpPort := "587" + + raw := `Subject: Password Reset + + + Dear {user}, + + We have reset your password to {pass}. Please logon to https://sfmarkets.com.au/broker to check your new credentials. + + There is no need to reply this mail. If you encounter any difficulties, please contact SuperFinance market directly. + + This is an automated email, and no one is monitoring this mailbox, please do not reply. + + Kind Regards + Biukop Mailing service team. + ` + + raw = strings.Replace(raw, "{user}", user.Display, -1) + raw = strings.Replace(raw, "{pass}", pass, -1) + // Message. + message := []byte(raw) + + // Authentication. + auth := smtp.PlainAuth("", from, password, smtpHost) + + // Sending email. + err := smtp.SendMail(smtpHost+":"+smtpPort, auth, from, to, message) + if err != nil { + fmt.Println(err) + return + } + fmt.Println("Email Sent Successfully!") +} diff --git a/apiV1EmailPass_test.go b/apiV1EmailPass_test.go new file mode 100644 index 0000000..09842d5 --- /dev/null +++ b/apiV1EmailPass_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestSendEmail(t *testing.T) { + + // sendEmailPassLink("sp@lawipac.com", "somepass") + +} diff --git a/apiV1PeopleList.go b/apiV1PeopleList.go index 9e5c435..4897bad 100644 --- a/apiV1PeopleList.go +++ b/apiV1PeopleList.go @@ -7,6 +7,7 @@ import ( "github.com/brianvoe/gofakeit/v6" log "github.com/sirupsen/logrus" "net/http" + "strings" ) func apiV1PeopleList(w http.ResponseWriter, r *http.Request, ss *loan.Session) { @@ -109,7 +110,7 @@ func apiV1PeopleExtraGet(w http.ResponseWriter, r *http.Request, ss *loan.Sessio ret := UserExtra{} ret.Role = loan.GetRoleById(id) //TODO; check manager and account role - switch ret.Role { + switch strings.ToLower(ret.Role) { case "people": apiV1SendJson(ret, w, r, ss) return diff --git a/apiV1StepUpload.go b/apiV1StepUpload.go new file mode 100644 index 0000000..ac3e8de --- /dev/null +++ b/apiV1StepUpload.go @@ -0,0 +1,170 @@ +package main + +import ( + "biukop.com/sfm/loan" + "bytes" + "database/sql" + "encoding/json" + log "github.com/sirupsen/logrus" + "io" + "net/http" + "strings" + "time" +) + +func apiV1StepUploadsPost(w http.ResponseWriter, r *http.Request, ss *loan.Session) { + id := r.URL.Path[len(apiV1Prefix+"step-upload/"):] //remove prefix + s := loan.Steps{} + e := s.Read(id) + if e != nil { + apiV1Client404Error(w, r, ss) + return + } + + if e != nil { + log.Error("cannot read step Id for new upload", s, e) + apiV1Server500Error(w, r) + return + } + + if s.LoanId != s.LoanId { + log.Error("loanId mis-match for step upload", s) + apiV1Client403Error(w, r, ss) + return + } + s.UploadedAt = time.Now() + + e = saveStepUploadToDb(&s, r) + if e != nil { + s.FileContent = s.FileContent[0:512] //only keep first 512 byte for log purpose + log.Println("failed to save step uploads", s, e) + apiV1Server500Error(w, r) + return + } + s.FileContent = nil + apiV1SendJson(s, w, r, ss) +} + +func saveStepUploadToDb(step *loan.Steps, r *http.Request) (e error) { + e = r.ParseMultipartForm(10 << 20) + if e != nil { + return + } + file, header, e := r.FormFile("files") + if e != nil { + log.Error("Error Getting StepUpload File", e) + return + } + + buf := new(strings.Builder) + n, err := io.Copy(buf, file) + if err != nil { + log.Error("Error copy StepUpload File to memory", e, n) + return err + } + step.FileName = header.Filename + step.FileSize = int(header.Size) + step.FileMime = header.Header.Get("Content-type") + step.FileContent = []byte(buf.String()) + + e = step.Write() + + return +} + +func apiV1StepUploadsDownload(w http.ResponseWriter, r *http.Request, ss *loan.Session) { + id := r.URL.Path[len(apiV1Prefix+"step-download/"):] //remove prefix + s := loan.Steps{} + e := s.ReadWithContent(id) + if e != nil { + if e != sql.ErrNoRows { + log.Warn("invalid upload id", e, id) + apiV1Client403Error(w, r, ss) + } + return + } + + w.Header().Set("Content-Disposition", "attachment; filename="+s.FileName) + w.Header().Set("Content-Type", s.FileMime) + http.ServeContent(w, r, s.FileName, s.UploadedAt, bytes.NewReader(s.FileContent)) +} + +func decodeJsonStep(r *http.Request) (ret loan.Steps, e error) { + decoder := json.NewDecoder(r.Body) + //decoder.DisallowUnknownFields() + e = decoder.Decode(&ret) + if e != nil { + log.Error("failed decoding json for Filtering full_loan_summary ", e.Error()) + return + } + return +} + +func apiV1StepUploadsGetID(w http.ResponseWriter, r *http.Request, ss *loan.Session) { + step, e := decodeJsonStep(r) + if e != nil || step.StepIndex <= 0 { + log.Error("unauthorized parameters for upload step attachment", step) + apiV1Client403Error(w, r, ss) + return + } + + e = step.GetIdByLoanIdAndIdx(step.LoanId, step.StepIndex) + if e != nil { + log.Error("cannot get step id for Loan, and index", step, e) + apiV1Client404Error(w, r, ss) + + } else { + apiV1SendJson(step, w, r, ss) + } +} + +func apiV1StepUploadsMetaPost(w http.ResponseWriter, r *http.Request, ss *loan.Session) { + step, e := decodeJsonStep(r) + if e != nil || step.StepIndex <= 0 { + log.Error("unauthorized parameters for upload step attachment", step) + apiV1Client403Error(w, r, ss) + return + } + + e = step.Write() + if e != nil { + log.Error("cannot get step id for Loan, and index", step, e) + apiV1Client404Error(w, r, ss) + } else { + apiV1SendJson(step, w, r, ss) + } +} + +func apiV1StepDelete(w http.ResponseWriter, r *http.Request, ss *loan.Session) { + id := r.URL.Path[len(apiV1Prefix+"step/"):] //remove prefix + step := loan.Steps{Id: id} + e := step.Read(id) + if e != nil { + apiV1Client404Error(w, r, ss) + return + } + e = step.Delete() + if e != nil { + apiV1Server500Error(w, r) + } else { + apiV1SendJson(true, w, r, ss) + } + return +} + +func apiV1StepDeleteFile(w http.ResponseWriter, r *http.Request, ss *loan.Session) { + id := r.URL.Path[len(apiV1Prefix+"step-file/"):] //remove prefix + step := loan.Steps{Id: id} + e := step.Read(id) + if e != nil { + apiV1Client404Error(w, r, ss) + return + } + e = step.DeleteFile() + if e != nil { + apiV1Server500Error(w, r) + } else { + apiV1SendJson(true, w, r, ss) + } + return +} diff --git a/apiV1Steps.go b/apiV1Steps.go new file mode 100644 index 0000000..f9e1e0f --- /dev/null +++ b/apiV1Steps.go @@ -0,0 +1,27 @@ +package main + +import ( + "biukop.com/sfm/loan" + log "github.com/sirupsen/logrus" + "net/http" + "strconv" +) + +func apiV1StepsMetaGet(w http.ResponseWriter, r *http.Request, ss *loan.Session) { + id := r.URL.Path[len(apiV1Prefix+"upload-meta/"):] //remove prefix + intId, e := strconv.Atoi(id) + if e != nil { + log.Println("invalid id for upload get", id, e) + apiV1Client403Error(w, r, ss) // bad request + return + } + + ulmeta := loan.Uploads{} + e = ulmeta.Read(int64(intId)) + if e != nil { + log.Println("upload not found", id, e) + apiV1Client404Error(w, r, ss) // bad request + return + } + apiV1SendJson(ulmeta, w, r, ss) +} diff --git a/apiv1.go b/apiv1.go index c1a8703..3a31892 100644 --- a/apiv1.go +++ b/apiv1.go @@ -110,6 +110,15 @@ func setupApiV1Handler() []apiV1HandlerMap { {"POST", "payout-paid/", apiV1PayOutPaid}, {"POST", "payout-unpaid/", apiV1PayOutUnpaid}, + {"POST", "step-upload/", apiV1StepUploadsPost}, + {"GET", "step-download/", apiV1StepUploadsDownload}, + {"POST", "step-id/", apiV1StepUploadsGetID}, + {"POST", "step-meta-update/", apiV1StepUploadsMetaPost}, + {"DELETE", "step/", apiV1StepDelete}, + {"DELETE", "step-file/", apiV1StepDeleteFile}, + + {"POST", "email-password/", apiV1EmailPassword}, + {"GET", "login", apiV1DumpRequest}, } } else { //production @@ -197,6 +206,15 @@ func setupApiV1Handler() []apiV1HandlerMap { {"POST", "payout-paid/", apiV1PayOutPaid}, {"POST", "payout-unpaid/", apiV1PayOutUnpaid}, + {"POST", "step-upload/", apiV1StepUploadsPost}, + {"GET", "step-download/", apiV1StepUploadsDownload}, + {"POST", "step-id/", apiV1StepUploadsGetID}, + {"POST", "step-meta-update/", apiV1StepUploadsMetaPost}, + {"DELETE", "step/", apiV1StepDelete}, + {"DELETE", "step-file/", apiV1StepDeleteFile}, + + {"POST", "email-password/", apiV1EmailPassword}, + {"GET", "login", apiV1EmptyResponse}, } } diff --git a/deploy/config.prod.json b/deploy/config.prod.json index 92f6804..589d3c3 100644 --- a/deploy/config.prod.json +++ b/deploy/config.prod.json @@ -1,7 +1,7 @@ { "Host":"0.0.0.0", "Port":"8080", - "DSN": "sp:sp@/syd_credit?parseTime=true&loc=Australia%2FSydney", + "DSN": "sp:sp@/syd_credit?parseTime=true&loc=Australia%2FSydney&collation=utf8mb4_0900_ai_ci", "TlsCert": "/home/c5016/ssl.combined", "TlsKey": "/home/c5016/ssl.key", "Debug": false,