put together the new account path
This commit is contained in:
+115
-2
@@ -10,6 +10,7 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -19,6 +20,7 @@ import (
|
|||||||
|
|
||||||
// ContactInfo stores the contact information for a user or community.
|
// ContactInfo stores the contact information for a user or community.
|
||||||
type ContactInfo struct {
|
type ContactInfo struct {
|
||||||
|
Mutex sync.Mutex
|
||||||
ContactId int32 `db:"contactid"`
|
ContactId int32 `db:"contactid"`
|
||||||
GivenName string `db:"given_name"`
|
GivenName string `db:"given_name"`
|
||||||
FamilyName string `db:"family_name"`
|
FamilyName string `db:"family_name"`
|
||||||
@@ -44,7 +46,106 @@ type ContactInfo struct {
|
|||||||
OwnerCommId int32 `db:"owner_commid"`
|
OwnerCommId int32 `db:"owner_commid"`
|
||||||
PhotoURL *string `db:"photo_url"`
|
PhotoURL *string `db:"photo_url"`
|
||||||
URL *string `db:"url"`
|
URL *string `db:"url"`
|
||||||
LastUpdate *time.Time
|
LastUpdate *time.Time `db:"lastupdate"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupCommunityContact looks up the ID of a contact for a community.
|
||||||
|
func lookupCommunityContact(id int32) (int32, error) {
|
||||||
|
var rc int32 = -1
|
||||||
|
rs, err := amdb.Query("SELECT contactid FROM contacts WHERE onwer_commid = ?", id)
|
||||||
|
if err == nil {
|
||||||
|
if rs.Next() {
|
||||||
|
rs.Scan(&rc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupUserContact looks up the ID of a contact for a user.
|
||||||
|
func lookupUserContact(uid int32) (int32, error) {
|
||||||
|
var rc int32 = -1
|
||||||
|
rs, err := amdb.Query("SELECT contactid FROM contacts WHERE owner_uid = ? AND owner_commid = -1", uid)
|
||||||
|
if err == nil {
|
||||||
|
if rs.Next() {
|
||||||
|
rs.Scan(&rc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save saves the contact info to the database.
|
||||||
|
* Returns:
|
||||||
|
* true if the E-mail address on this account has been changed, false if not.
|
||||||
|
* Standard Go error status.
|
||||||
|
*/
|
||||||
|
func (ci *ContactInfo) Save() (bool, error) {
|
||||||
|
ci.Mutex.Lock()
|
||||||
|
defer ci.Mutex.Unlock()
|
||||||
|
updateMode := false
|
||||||
|
emailChange := true
|
||||||
|
if ci.ContactId <= 0 {
|
||||||
|
var nx int32
|
||||||
|
var err error
|
||||||
|
if ci.OwnerCommId > 0 {
|
||||||
|
nx, err = lookupCommunityContact(ci.OwnerCommId)
|
||||||
|
} else {
|
||||||
|
nx, err = lookupUserContact(ci.OwnerUid)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if nx > 0 {
|
||||||
|
ci.ContactId = nx
|
||||||
|
updateMode = true
|
||||||
|
emailChange = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateMode = true
|
||||||
|
emailChange = false
|
||||||
|
}
|
||||||
|
if !emailChange {
|
||||||
|
rs, err := amdb.Query("SELECT contactid FROM contacts WHERE contactid = ? AND email = ?", ci.ContactId, ci.Email)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if !rs.Next() {
|
||||||
|
emailChange = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if updateMode {
|
||||||
|
_, err := amdb.Exec(`UPDATE contacts SET given_name = ?, family_name = ?, middle_init = ?, prefix = ?, suffix = ?, company = ?,
|
||||||
|
addr1 = ?, addr2 = ?, locality = ?, region = ?, pcode = ?, country = ?, phone = ?, fax = ?, mobile = ?, email = ?,
|
||||||
|
pvt_addr = ?, pvt_phone = ?, pvt_fax = ?, pvt_email = ?, photo_url = ?, url = ?, lastupdate = NOW()
|
||||||
|
WHERE contactid = ?`, ci.GivenName, ci.FamilyName, ci.MiddleInit, ci.Prefix, ci.Suffix, ci.Company,
|
||||||
|
ci.Addr1, ci.Addr2, ci.Locality, ci.Region, ci.PostalCode, ci.Country, ci.Phone, ci.Fax, ci.Mobile, ci.Email,
|
||||||
|
ci.PrivateAddr, ci.PrivatePhone, ci.PrivateFax, ci.PrivateEmail, ci.PhotoURL, ci.URL, ci.ContactId)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res, err := amdb.Exec(`INSERT INTO contacts (given_name, family_name, middle_init, prefix, suffix, company, addr1,
|
||||||
|
addr2, locality, region, pcode, country, phone, fax, mobile, email, pvt_addr, pvt_phone, pvt_fax,
|
||||||
|
pvt_email, owner_uid, owner_commid, photo_url, url, lastupdate)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())`,
|
||||||
|
ci.GivenName, ci.FamilyName, ci.MiddleInit, ci.Prefix, ci.Suffix, ci.Company, ci.Addr1, ci.Addr2,
|
||||||
|
ci.Locality, ci.Region, ci.PostalCode, ci.Country, ci.Phone, ci.Fax, ci.Mobile, ci.Email,
|
||||||
|
ci.PrivateAddr, ci.PrivatePhone, ci.PrivateFax, ci.PrivateEmail, ci.OwnerUid, ci.OwnerCommId, ci.PhotoURL, ci.URL)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
lii, _ := res.LastInsertId()
|
||||||
|
ci.ContactId = int32(lii)
|
||||||
|
contactCache.Add(ci.ContactId, ci)
|
||||||
|
}
|
||||||
|
rs, err := amdb.Query("SELECT lastupdate FROM contacts WHERE contactid = ?", ci.ContactId)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if !rs.Next() {
|
||||||
|
return false, errors.New("internal error rereading update timestamp")
|
||||||
|
}
|
||||||
|
rs.Scan(&ci.LastUpdate)
|
||||||
|
return emailChange, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// contactCache is the cache for ContactInfo objects.
|
// contactCache is the cache for ContactInfo objects.
|
||||||
@@ -82,7 +183,8 @@ func internalContactInfo(id int32) (*ContactInfo, error) {
|
|||||||
* Parameters:
|
* Parameters:
|
||||||
* id - The contact info ID top retrieve.
|
* id - The contact info ID top retrieve.
|
||||||
* Returns:
|
* Returns:
|
||||||
*
|
* ContactInfo retrieved, or nil.
|
||||||
|
* Standard Go error status.
|
||||||
*/
|
*/
|
||||||
func AmGetContactInfo(id int32) (*ContactInfo, error) {
|
func AmGetContactInfo(id int32) (*ContactInfo, error) {
|
||||||
getContactMutex.Lock()
|
getContactMutex.Lock()
|
||||||
@@ -100,3 +202,14 @@ func AmGetContactInfo(id int32) (*ContactInfo, error) {
|
|||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* AmNewUserContactInfo creates a new contact info record for the user.
|
||||||
|
* Parameters:
|
||||||
|
* uid - The UID of the owner of this contact info.
|
||||||
|
* Returns:
|
||||||
|
* New ContactInfo structure.
|
||||||
|
*/
|
||||||
|
func AmNewUserContactInfo(uid int32) *ContactInfo {
|
||||||
|
rc := ContactInfo{OwnerUid: uid, OwnerCommId: -1}
|
||||||
|
return &rc
|
||||||
|
}
|
||||||
|
|||||||
@@ -136,6 +136,18 @@ func (u *User) ConfirmEMailAddress(confnum int32, remoteIP string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEmailConfirmationNumber creates a new confirmation number for a user and saves it off.
|
||||||
|
func (u *User) NewEmailConfirmationNumber() error {
|
||||||
|
u.Mutex.Lock()
|
||||||
|
defer u.Mutex.Unlock()
|
||||||
|
newnum := newEmailConfirmationNumber()
|
||||||
|
_, err := amdb.Exec("UPDATE user SET email_confnum = ? WHERE uid = ?", newnum, u.Uid)
|
||||||
|
if err != nil {
|
||||||
|
u.EmailConfNum = newnum
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
/* AmGetUser returns a reference to the specified user.
|
/* AmGetUser returns a reference to the specified user.
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* uid - The UID of the user.
|
* uid - The UID of the user.
|
||||||
|
|||||||
@@ -187,6 +187,20 @@ func VerifyEmailForm(ctxt ui.AmContext) (string, any, error) {
|
|||||||
return ui.ErrorPage(ctxt, err)
|
return ui.ErrorPage(ctxt, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sendEmailConfirmationEmail(user *database.User, ci *database.ContactInfo, remoteIP string) error {
|
||||||
|
if ci != nil && ci.Email != nil && *ci.Email != "" {
|
||||||
|
msg := email.AmNewEmailMessage(user.Uid, remoteIP)
|
||||||
|
msg.AddTo(*ci.Email, "")
|
||||||
|
msg.SetTemplate("verify_email.jet")
|
||||||
|
msg.AddVariable("username", user.Username)
|
||||||
|
msg.AddVariable("confnum", user.EmailConfNum)
|
||||||
|
msg.Send()
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("cannot find email address")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* VerifyEmail handles E-mail address verification.
|
/* VerifyEmail handles E-mail address verification.
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* ctxt - The AmContext for the request.
|
* ctxt - The AmContext for the request.
|
||||||
@@ -223,15 +237,9 @@ func VerifyEMail(ctxt ui.AmContext) (string, any, error) {
|
|||||||
var ci *database.ContactInfo
|
var ci *database.ContactInfo
|
||||||
ci, err = user.ContactInfo()
|
ci, err = user.ContactInfo()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if ci != nil && ci.Email != nil && *ci.Email != "" {
|
err = user.NewEmailConfirmationNumber()
|
||||||
msg := email.AmNewEmailMessage(user.Uid, ctxt.RemoteIP())
|
if err == nil {
|
||||||
msg.AddTo(*ci.Email, "")
|
err = sendEmailConfirmationEmail(user, ci, ctxt.RemoteIP())
|
||||||
msg.SetTemplate("verify_email.jet")
|
|
||||||
msg.AddVariable("username", user.Username)
|
|
||||||
msg.AddVariable("confnum", user.EmailConfNum)
|
|
||||||
msg.Send()
|
|
||||||
} else {
|
|
||||||
err = errors.New("cannot find email address")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -309,6 +317,14 @@ func NewAccountForm(ctxt ui.AmContext) (string, any, error) {
|
|||||||
return ui.ErrorPage(ctxt, err)
|
return ui.ErrorPage(ctxt, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NewAccount handles creating a new Amsterdam account.
|
||||||
|
* Parameters:
|
||||||
|
* ctxt - The AmContext for the request.
|
||||||
|
* Returns:
|
||||||
|
* Command string dictating what to be rendered.
|
||||||
|
* Data as a parameter for the command string.
|
||||||
|
* Standard Go error status.
|
||||||
|
*/
|
||||||
func NewAccount(ctxt ui.AmContext) (string, any, error) {
|
func NewAccount(ctxt ui.AmContext) (string, any, error) {
|
||||||
// If user is already logged in, this is an error.
|
// If user is already logged in, this is an error.
|
||||||
if !ctxt.CurrentUser().IsAnon {
|
if !ctxt.CurrentUser().IsAnon {
|
||||||
@@ -344,8 +360,30 @@ func NewAccount(ctxt ui.AmContext) (string, any, error) {
|
|||||||
user, err = database.AmCreateNewUser(dlg.Field("user").Value, dlg.Field("pass1").Value,
|
user, err = database.AmCreateNewUser(dlg.Field("user").Value, dlg.Field("pass1").Value,
|
||||||
dlg.Field("remind").Value, dlg.Field("dob").AsDate(), ctxt.RemoteIP())
|
dlg.Field("remind").Value, dlg.Field("dob").AsDate(), ctxt.RemoteIP())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// TODO: set up contact info
|
// create and save contact info
|
||||||
_ = user
|
ci := database.AmNewUserContactInfo(user.Uid)
|
||||||
|
ci.Prefix = dlg.Field("prefix").ValPtr()
|
||||||
|
ci.GivenName = dlg.Field("first").Value
|
||||||
|
ci.MiddleInit = dlg.Field("mid").Value
|
||||||
|
if ci.MiddleInit == "" {
|
||||||
|
ci.MiddleInit = " "
|
||||||
|
}
|
||||||
|
ci.FamilyName = dlg.Field("last").Value
|
||||||
|
ci.Suffix = dlg.Field("suffix").ValPtr()
|
||||||
|
ci.Locality = dlg.Field("loc").ValPtr()
|
||||||
|
ci.Region = dlg.Field("reg").ValPtr()
|
||||||
|
ci.PostalCode = dlg.Field("pcode").ValPtr()
|
||||||
|
ci.Country = dlg.Field("country").ValPtr()
|
||||||
|
ci.Email = dlg.Field("email").ValPtr()
|
||||||
|
_, err = ci.Save()
|
||||||
|
if err == nil {
|
||||||
|
err = sendEmailConfirmationEmail(user, ci, ctxt.RemoteIP())
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
// user is now logged in! redirect to E-mail verification
|
||||||
|
ctxt.ReplaceUser(user)
|
||||||
|
return "redirect", "/verify?tgt=" + url.PathEscape(target), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,14 @@ func (fld *DialogItem) AsDate() *time.Time {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValPtr returns the value of a field as a string pointer, or nil if the field is empty.
|
||||||
|
func (fld *DialogItem) ValPtr() *string {
|
||||||
|
if fld.Value == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &fld.Value
|
||||||
|
}
|
||||||
|
|
||||||
/* Field returns a pointer to a dialog's field, given its name.
|
/* Field returns a pointer to a dialog's field, given its name.
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* name - The name of the field to find.
|
* name - The name of the field to find.
|
||||||
|
|||||||
Reference in New Issue
Block a user