| @@ -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!") | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| package main | |||
| import "testing" | |||
| func TestSendEmail(t *testing.T) { | |||
| // sendEmailPassLink("sp@lawipac.com", "somepass") | |||
| } | |||
| @@ -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 | |||
| @@ -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 | |||
| } | |||
| @@ -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) | |||
| } | |||
| @@ -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}, | |||
| } | |||
| } | |||
| @@ -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, | |||