From 6cc6b6d70fde6dbba626d9858f53efbce232a546 Mon Sep 17 00:00:00 2001 From: Harvey Kandola Date: Mon, 25 Jul 2016 11:40:26 -0700 Subject: [PATCH 1/4] GenerateRandom function added --- core/api/util/password.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/api/util/password.go b/core/api/util/password.go index da7411a4..c549fc97 100644 --- a/core/api/util/password.go +++ b/core/api/util/password.go @@ -1,11 +1,11 @@ // Copyright 2016 Documize Inc. . All rights reserved. // -// This software (Documize Community Edition) is licensed under +// This software (Documize Community Edition) is licensed under // GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html // // You can operate outside the AGPL restrictions by purchasing // Documize Enterprise Edition and obtaining a commercial license -// by contacting . +// by contacting . // // https://documize.com @@ -22,17 +22,17 @@ import ( // GenerateRandomPassword provides a string suitable for use as a password. func GenerateRandomPassword() string { - c := 5 - b := make([]byte, c) - _, err := rand.Read(b) - log.IfErr(err) - return hex.EncodeToString(b) + return GenerateRandom(5) } // GenerateSalt provides a string suitable for use as a salt value. func GenerateSalt() string { - c := 20 - b := make([]byte, c) + return GenerateRandom(20) +} + +// GenerateRandom returns a string of the specified length using crypo/rand +func GenerateRandom(size int) string { + b := make([]byte, size) _, err := rand.Read(b) log.IfErr(err) return hex.EncodeToString(b) From 2e39b7a4714264e99440e89f93a24b79404c9d13 Mon Sep 17 00:00:00 2001 From: Harvey Kandola Date: Mon, 25 Jul 2016 12:25:23 -0700 Subject: [PATCH 2/4] refactored getAppURL --- core/api/endpoint/init.go | 17 ++--------------- core/api/endpoint/label_endpoint.go | 6 +++--- core/api/endpoint/meta_endpoint.go | 6 +++--- core/api/endpoint/user_endpoint.go | 8 +++----- core/api/request/context.go | 11 +++++++++++ 5 files changed, 22 insertions(+), 26 deletions(-) diff --git a/core/api/endpoint/init.go b/core/api/endpoint/init.go index 38155dc1..9c564ad3 100644 --- a/core/api/endpoint/init.go +++ b/core/api/endpoint/init.go @@ -1,11 +1,11 @@ // Copyright 2016 Documize Inc. . All rights reserved. // -// This software (Documize Community Edition) is licensed under +// This software (Documize Community Edition) is licensed under // GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html // // You can operate outside the AGPL restrictions by purchasing // Documize Enterprise Edition and obtaining a commercial license -// by contacting . +// by contacting . // // https://documize.com @@ -15,7 +15,6 @@ import ( "fmt" "net/http" - "github.com/documize/community/core/api/request" "github.com/documize/community/core/api/store" "github.com/documize/community/core/log" ) @@ -26,18 +25,6 @@ func init() { storageProvider = new(store.LocalStorageProvider) } -//getAppURL returns full HTTP url for the app -func getAppURL(c request.Context, endpoint string) string { - - scheme := "http://" - - if c.SSL { - scheme = "https://" - } - - return fmt.Sprintf("%s%s/%s", scheme, c.AppURL, endpoint) -} - func writePayloadError(w http.ResponseWriter, method string, err error) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(http.StatusBadRequest) diff --git a/core/api/endpoint/label_endpoint.go b/core/api/endpoint/label_endpoint.go index 63b78495..7aed3ad3 100644 --- a/core/api/endpoint/label_endpoint.go +++ b/core/api/endpoint/label_endpoint.go @@ -407,7 +407,7 @@ func SetFolderPermissions(w http.ResponseWriter, r *http.Request) { hasEveryoneRole := false roleCount := 0 - url := getAppURL(p.Context, fmt.Sprintf("s/%s/%s", label.RefID, utility.MakeSlug(label.Name))) + url := p.Context.GetAppURL(fmt.Sprintf("s/%s/%s", label.RefID, utility.MakeSlug(label.Name))) for _, role := range model.Roles { role.OrgID = p.Context.OrgID @@ -742,13 +742,13 @@ func InviteToFolder(w http.ResponseWriter, r *http.Request) { return } - url := getAppURL(p.Context, fmt.Sprintf("s/%s/%s", label.RefID, utility.MakeSlug(label.Name))) + url := p.Context.GetAppURL(fmt.Sprintf("s/%s/%s", label.RefID, utility.MakeSlug(label.Name))) go mail.ShareFolderExistingUser(email, inviter.Fullname(), url, label.Name, model.Message) log.Info(fmt.Sprintf("%s is sharing space %s with existing user %s", inviter.Email, label.Name, email)) } else { // On-board new user if strings.Contains(email, "@") { - url := getAppURL(p.Context, fmt.Sprintf("auth/share/%s/%s", label.RefID, utility.MakeSlug(label.Name))) + url := p.Context.GetAppURL(fmt.Sprintf("auth/share/%s/%s", label.RefID, utility.MakeSlug(label.Name))) err = inviteNewUserToSharedFolder(p, email, inviter, url, label, model.Message) if err != nil { diff --git a/core/api/endpoint/meta_endpoint.go b/core/api/endpoint/meta_endpoint.go index 6e0d0e24..6cec5a05 100644 --- a/core/api/endpoint/meta_endpoint.go +++ b/core/api/endpoint/meta_endpoint.go @@ -80,7 +80,7 @@ Disallow: / // Anonymous access would mean we allow bots to crawl. if org.AllowAnonymousAccess { - sitemap := getAppURL(p.Context, "sitemap.xml") + sitemap := p.Context.GetAppURL("sitemap.xml") robots = fmt.Sprintf( `User-agent: * Disallow: /settings/ @@ -138,7 +138,7 @@ func GetSitemap(w http.ResponseWriter, r *http.Request) { for _, folder := range folders { var item sitemapItem - item.URL = getAppURL(p.Context, fmt.Sprintf("s/%s/%s", folder.RefID, utility.MakeSlug(folder.Name))) + item.URL = p.Context.GetAppURL(fmt.Sprintf("s/%s/%s", folder.RefID, utility.MakeSlug(folder.Name))) item.Date = folder.Revised.Format("2006-01-02T15:04:05.999999-07:00") items = append(items, item) } @@ -152,7 +152,7 @@ func GetSitemap(w http.ResponseWriter, r *http.Request) { for _, document := range documents { var item sitemapItem - item.URL = getAppURL(p.Context, fmt.Sprintf("s/%s/%s/d/%s/%s", + item.URL = p.Context.GetAppURL(fmt.Sprintf("s/%s/%s/d/%s/%s", document.FolderID, utility.MakeSlug(document.Folder), document.DocumentID, utility.MakeSlug(document.Document))) item.Date = document.Revised.Format("2006-01-02T15:04:05.999999-07:00") items = append(items, item) diff --git a/core/api/endpoint/user_endpoint.go b/core/api/endpoint/user_endpoint.go index a7b44d13..f1181eb6 100644 --- a/core/api/endpoint/user_endpoint.go +++ b/core/api/endpoint/user_endpoint.go @@ -174,13 +174,13 @@ func AddUser(w http.ResponseWriter, r *http.Request) { auth := fmt.Sprintf("%s:%s:%s", p.Context.AppURL, userModel.Email, requestedPassword[:size]) encrypted := utility.EncodeBase64([]byte(auth)) - url := fmt.Sprintf("%s/%s", getAppURL(p.Context, "auth/sso"), url.QueryEscape(string(encrypted))) + url := fmt.Sprintf("%s/%s", p.Context.GetAppURL("auth/sso"), url.QueryEscape(string(encrypted))) go mail.InviteNewUser(userModel.Email, inviter.Fullname(), url, userModel.Email, requestedPassword) log.Info(fmt.Sprintf("%s invited by %s on %s", userModel.Email, inviter.Email, p.Context.AppURL)) } else { - go mail.InviteExistingUser(userModel.Email, inviter.Fullname(), getAppURL(p.Context, "")) + go mail.InviteExistingUser(userModel.Email, inviter.Fullname(), p.Context.GetAppURL("")) log.Info(fmt.Sprintf("%s is giving access to an existing user %s", inviter.Email, userModel.Email)) } @@ -605,9 +605,7 @@ func ForgotUserPassword(w http.ResponseWriter, r *http.Request) { log.IfErr(tx.Commit()) - appURL := getAppURL(p.Context, fmt.Sprintf("auth/reset/%s", token)) - - fmt.Println(appURL) + appURL := p.Context.GetAppURL(fmt.Sprintf("auth/reset/%s", token)) go mail.PasswordReset(user.Email, appURL) diff --git a/core/api/request/context.go b/core/api/request/context.go index f6174bda..05e79862 100644 --- a/core/api/request/context.go +++ b/core/api/request/context.go @@ -42,6 +42,17 @@ type Context struct { Transaction *sqlx.Tx } +//GetAppURL returns full HTTP url for the app +func (c *Context) GetAppURL(endpoint string) string { + scheme := "http://" + + if c.SSL { + scheme = "https://" + } + + return fmt.Sprintf("%s%s/%s", scheme, c.AppURL, endpoint) +} + // NewContext simply returns a blank Context type. func NewContext() Context { return Context{} From 56fe0471361934d1eb776875585a05f3b61c7c61 Mon Sep 17 00:00:00 2001 From: Harvey Kandola Date: Mon, 25 Jul 2016 14:03:11 -0700 Subject: [PATCH 3/4] public mail methods --- core/api/mail/mailer.go | 51 +++++++++++++++++++++-------------------- core/api/mail/smtp.go | 11 +++++---- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/core/api/mail/mailer.go b/core/api/mail/mailer.go index c34a9b3b..93e622bb 100644 --- a/core/api/mail/mailer.go +++ b/core/api/mail/mailer.go @@ -20,8 +20,8 @@ import ( "net/smtp" "github.com/documize/community/core/api/request" - "github.com/documize/community/core/web" "github.com/documize/community/core/log" + "github.com/documize/community/core/web" ) // InviteNewUser invites someone new providing credentials, explaining the product and stating who is inviting them. @@ -44,8 +44,8 @@ func InviteNewUser(recipient, inviter, url, username, password string) { subject := fmt.Sprintf("%s has invited you to Documize", inviter) - e := newEmail() - e.From = creds.SMTPsender() + e := NewEmail() + e.From = SMTPCreds.SMTPsender() e.To = []string{recipient} e.Subject = subject @@ -68,7 +68,7 @@ func InviteNewUser(recipient, inviter, url, username, password string) { log.IfErr(t.Execute(buffer, ¶meters)) e.HTML = buffer.Bytes() - err = e.Send(getHost(), getAuth()) + err = e.Send(GetHost(), GetAuth()) if err != nil { log.Error(fmt.Sprintf("%s - unable to send email", method), err) @@ -95,8 +95,8 @@ func InviteExistingUser(recipient, inviter, url string) { subject := fmt.Sprintf("%s has invited you to their Documize account", inviter) - e := newEmail() - e.From = creds.SMTPsender() + e := NewEmail() + e.From = SMTPCreds.SMTPsender() e.To = []string{recipient} e.Subject = subject @@ -115,7 +115,7 @@ func InviteExistingUser(recipient, inviter, url string) { log.IfErr(t.Execute(buffer, ¶meters)) e.HTML = buffer.Bytes() - err = e.Send(getHost(), getAuth()) + err = e.Send(GetHost(), GetAuth()) if err != nil { log.Error(fmt.Sprintf("%s - unable to send email", method), err) @@ -137,8 +137,8 @@ func PasswordReset(recipient, url string) { subject := "Documize password reset request" - e := newEmail() - e.From = creds.SMTPsender() //e.g. "Documize " + e := NewEmail() + e.From = SMTPCreds.SMTPsender() //e.g. "Documize " e.To = []string{recipient} e.Subject = subject @@ -155,7 +155,7 @@ func PasswordReset(recipient, url string) { log.IfErr(t.Execute(buffer, ¶meters)) e.HTML = buffer.Bytes() - err = e.Send(getHost(), getAuth()) + err = e.Send(GetHost(), GetAuth()) if err != nil { log.Error(fmt.Sprintf("%s - unable to send email", method), err) @@ -182,8 +182,8 @@ func ShareFolderExistingUser(recipient, inviter, url, folder, intro string) { subject := fmt.Sprintf("%s has shared %s with you", inviter, folder) - e := newEmail() - e.From = creds.SMTPsender() + e := NewEmail() + e.From = SMTPCreds.SMTPsender() e.To = []string{recipient} e.Subject = subject @@ -206,7 +206,7 @@ func ShareFolderExistingUser(recipient, inviter, url, folder, intro string) { log.IfErr(t.Execute(buffer, ¶meters)) e.HTML = buffer.Bytes() - err = e.Send(getHost(), getAuth()) + err = e.Send(GetHost(), GetAuth()) if err != nil { log.Error(fmt.Sprintf("%s - unable to send email", method), err) @@ -233,8 +233,8 @@ func ShareFolderNewUser(recipient, inviter, url, folder, invitationMessage strin subject := fmt.Sprintf("%s has shared %s with you on Documize", inviter, folder) - e := newEmail() - e.From = creds.SMTPsender() + e := NewEmail() + e.From = SMTPCreds.SMTPsender() e.To = []string{recipient} e.Subject = subject @@ -257,14 +257,15 @@ func ShareFolderNewUser(recipient, inviter, url, folder, invitationMessage strin log.IfErr(t.Execute(buffer, ¶meters)) e.HTML = buffer.Bytes() - err = e.Send(getHost(), getAuth()) + err = e.Send(GetHost(), GetAuth()) if err != nil { log.Error(fmt.Sprintf("%s - unable to send email", method), err) } } -var creds = struct{ SMTPuserid, SMTPpassword, SMTPhost, SMTPport, SMTPsender func() string }{ +// SMTPCreds return SMTP configuration. +var SMTPCreds = struct{ SMTPuserid, SMTPpassword, SMTPhost, SMTPport, SMTPsender func() string }{ func() string { return request.ConfigString("SMTP", "userid") }, func() string { return request.ConfigString("SMTP", "password") }, func() string { return request.ConfigString("SMTP", "host") }, @@ -278,16 +279,16 @@ var creds = struct{ SMTPuserid, SMTPpassword, SMTPhost, SMTPport, SMTPsender fun func() string { return request.ConfigString("SMTP", "sender") }, } -// Helper to return SMTP credentials -func getAuth() smtp.Auth { - a := smtp.PlainAuth("", creds.SMTPuserid(), creds.SMTPpassword(), creds.SMTPhost()) - //fmt.Printf("DEBUG getAuth() = %#v\n", a) +// GetAuth to return SMTP credentials +func GetAuth() smtp.Auth { + a := smtp.PlainAuth("", SMTPCreds.SMTPuserid(), SMTPCreds.SMTPpassword(), SMTPCreds.SMTPhost()) + //fmt.Printf("DEBUG GetAuth() = %#v\n", a) return a } -// Helper to return SMTP host details -func getHost() string { - h := creds.SMTPhost() + ":" + creds.SMTPport() - //fmt.Printf("DEBUG getHost() = %#v\n", h) +// GetHost to return SMTP host details +func GetHost() string { + h := SMTPCreds.SMTPhost() + ":" + SMTPCreds.SMTPport() + //fmt.Printf("DEBUG GetHost() = %#v\n", h) return h } diff --git a/core/api/mail/smtp.go b/core/api/mail/smtp.go index 20fb6206..8f2bfe62 100644 --- a/core/api/mail/smtp.go +++ b/core/api/mail/smtp.go @@ -1,11 +1,11 @@ // Copyright 2016 Documize Inc. . All rights reserved. // -// This software (Documize Community Edition) is licensed under +// This software (Documize Community Edition) is licensed under // GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html // // You can operate outside the AGPL restrictions by purchasing // Documize Enterprise Edition and obtaining a commercial license -// by contacting . +// by contacting . // // https://documize.com @@ -45,7 +45,6 @@ import ( "encoding/base64" "errors" "fmt" - "github.com/documize/community/core/log" "io" "mime" "mime/multipart" @@ -56,6 +55,8 @@ import ( "path/filepath" "strings" "time" + + "github.com/documize/community/core/log" ) const ( @@ -77,8 +78,8 @@ type Email struct { ReadReceipt []string } -// newEmail creates an Email, and returns the pointer to it. -func newEmail() *Email { +// NewEmail creates an Email, and returns the pointer to it. +func NewEmail() *Email { return &Email{Headers: textproto.MIMEHeader{}} } From 170c20c8bcd92a22fa7680671ecd07d7110ac13c Mon Sep 17 00:00:00 2001 From: Harvey Kandola Date: Mon, 25 Jul 2016 17:32:46 -0700 Subject: [PATCH 4/4] WriteJSON method --- core/api/util/writeHTTP.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/core/api/util/writeHTTP.go b/core/api/util/writeHTTP.go index 1c5792b2..130d57a9 100644 --- a/core/api/util/writeHTTP.go +++ b/core/api/util/writeHTTP.go @@ -12,6 +12,7 @@ package util import ( + "encoding/json" "fmt" "net/http" @@ -124,3 +125,27 @@ func WriteSuccessEmptyJSON(w http.ResponseWriter) { _, err := w.Write([]byte("{}")) log.IfErr(err) } + +func WriteMarshalError(w http.ResponseWriter, err error) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.WriteHeader(http.StatusBadRequest) + _, err2 := w.Write([]byte("{Error: 'JSON marshal failed'}")) + log.IfErr(err2) + log.Error("Failed to JSON marshal", err) +} + +// WriteJSON serializes data as JSON to HTTP response. +func WriteJSON(w http.ResponseWriter, v interface{}) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.WriteHeader(http.StatusOK) + + j, err := json.Marshal(v) + + if err != nil { + WriteMarshalError(w, err) + return + } + + _, err = w.Write(j) + log.IfErr(err) +}