removed the defer idiom for storing audit records; it's not necessary, because AmStoreAudit just pushes the audit record to the writer goroutine anyway

This commit is contained in:
2026-02-21 18:24:29 -07:00
parent 5acb67106c
commit f48d97868d
5 changed files with 45 additions and 125 deletions
+2 -6
View File
@@ -854,10 +854,6 @@ func AmSetCommunityProperty(ctx context.Context, cid int32, ndx int32, val *stri
*/ */
func AmCreateCommunity(ctx context.Context, name string, alias string, hostUid int32, language *string, synopsis *string, func AmCreateCommunity(ctx context.Context, name string, alias string, hostUid int32, language *string, synopsis *string,
rules *string, joinkey *string, hideDirectory bool, hideSearch bool, remoteIP string) (*Community, error) { rules *string, joinkey *string, hideDirectory bool, hideSearch bool, remoteIP string) (*Community, error) {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -917,8 +913,8 @@ func AmCreateCommunity(ctx context.Context, name string, alias string, hostUid i
success = true success = true
// operation was a success - add an audit record // operation was a success - add an audit record
ar = AmNewCommAudit(AuditCommunityCreate, hostUid, comm.Id, remoteIP, fmt.Sprintf("id=%d", comm.Id), AmStoreAudit(AmNewCommAudit(AuditCommunityCreate, hostUid, comm.Id, remoteIP, fmt.Sprintf("id=%d", comm.Id),
fmt.Sprintf("name=%s", comm.Name), fmt.Sprintf("alias=%s", comm.Alias)) fmt.Sprintf("name=%s", comm.Name), fmt.Sprintf("alias=%s", comm.Alias)))
return comm, nil return comm, nil
} }
+1 -5
View File
@@ -1214,10 +1214,6 @@ func AmCreateConference(ctx context.Context, comm *Community, name, alias, descr
newConf.CreateLevel = AmDefaultRole("Conference.Create.Public").Level() newConf.CreateLevel = AmDefaultRole("Conference.Create.Public").Level()
} }
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -1290,6 +1286,6 @@ func AmCreateConference(ctx context.Context, comm *Community, name, alias, descr
// Add the new conference to the cache, and create our audit record. // Add the new conference to the cache, and create our audit record.
conferenceCache.Add(rc[0].ConfId, &(rc[0])) conferenceCache.Add(rc[0].ConfId, &(rc[0]))
ar = AmNewCommAudit(AuditConferenceCreate, u.Uid, comm.Id, ipaddr, fmt.Sprintf("confid=%d", rc[0].ConfId), fmt.Sprintf("name=%s", name), fmt.Sprintf("alias=%s", alias)) AmStoreAudit(AmNewCommAudit(AuditConferenceCreate, u.Uid, comm.Id, ipaddr, fmt.Sprintf("confid=%d", rc[0].ConfId), fmt.Sprintf("name=%s", name), fmt.Sprintf("alias=%s", alias)))
return &(rc[0]), nil return &(rc[0]), nil
} }
+10 -38
View File
@@ -164,10 +164,6 @@ func (p *PostHeader) AttachmentData(ctx context.Context, bugWorkaround bool) ([]
* Standard Go error status. * Standard Go error status.
*/ */
func (p *PostHeader) SetAttachment(ctx context.Context, u *User, fileName string, mimeType string, length int32, data []byte, comm *Community, ipaddr string) error { func (p *PostHeader) SetAttachment(ctx context.Context, u *User, fileName string, mimeType string, length int32, data []byte, comm *Community, ipaddr string) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
if p.ScribbleDate != nil && p.ScribbleUid != nil { if p.ScribbleDate != nil && p.ScribbleUid != nil {
return errors.New("cannot attach to scribbled post") return errors.New("cannot attach to scribbled post")
} }
@@ -209,8 +205,8 @@ func (p *PostHeader) SetAttachment(ctx context.Context, u *User, fileName string
_, err = amdb.ExecContext(ctx, "INSERT INTO postattach (postid, datalen, filename, mimetype, stgmethod, data) VALUES (?, ?, ?, ?, ?, ?)", _, err = amdb.ExecContext(ctx, "INSERT INTO postattach (postid, datalen, filename, mimetype, stgmethod, data) VALUES (?, ?, ?, ?, ?, ?)",
p.PostId, length, fileName, mimeType, stgmethod, realData) p.PostId, length, fileName, mimeType, stgmethod, realData)
// Generate an audit record. // Generate an audit record.
ar = AmNewCommAudit(AuditConferenceUploadAttachment, u.Uid, comm.Id, ipaddr, fmt.Sprintf("post=%d", p.PostId), AmStoreAudit(AmNewCommAudit(AuditConferenceUploadAttachment, u.Uid, comm.Id, ipaddr, fmt.Sprintf("post=%d", p.PostId),
fmt.Sprintf("len=%d,type=%s,name=%s,method=%d", length, mimeType, fileName, stgmethod)) fmt.Sprintf("len=%d,type=%s,name=%s,method=%d", length, mimeType, fileName, stgmethod)))
return err return err
} }
@@ -278,10 +274,6 @@ func (p *PostHeader) Link(ctx context.Context, scope string) (string, error) {
// SetHidden sets the "hidden" flag on a post. // SetHidden sets the "hidden" flag on a post.
func (p *PostHeader) SetHidden(ctx context.Context, u *User, flag bool, comm *Community, ipaddr string) error { func (p *PostHeader) SetHidden(ctx context.Context, u *User, flag bool, comm *Community, ipaddr string) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
if p.ScribbleDate != nil && p.ScribbleUid != nil { if p.ScribbleDate != nil && p.ScribbleUid != nil {
return errors.New("cannot hide or unhide scribbled post") return errors.New("cannot hide or unhide scribbled post")
} }
@@ -291,17 +283,13 @@ func (p *PostHeader) SetHidden(ctx context.Context, u *User, flag bool, comm *Co
_, err := amdb.ExecContext(ctx, "UPDATE posts SET hidden = ? WHERE postid = ?", flag, p.PostId) _, err := amdb.ExecContext(ctx, "UPDATE posts SET hidden = ? WHERE postid = ?", flag, p.PostId)
if err == nil { if err == nil {
p.Hidden = flag p.Hidden = flag
ar = AmNewCommAudit(AuditConferenceHideMessage, u.Uid, comm.Id, ipaddr, fmt.Sprintf("post=%d", p.PostId), fmt.Sprintf("hidden=%t", flag)) AmStoreAudit(AmNewCommAudit(AuditConferenceHideMessage, u.Uid, comm.Id, ipaddr, fmt.Sprintf("post=%d", p.PostId), fmt.Sprintf("hidden=%t", flag)))
} }
return err return err
} }
// Scribble causes a post to be scribbled. // Scribble causes a post to be scribbled.
func (p *PostHeader) Scribble(ctx context.Context, u *User, comm *Community, ipaddr string) error { func (p *PostHeader) Scribble(ctx context.Context, u *User, comm *Community, ipaddr string) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
if p.ScribbleDate != nil && p.ScribbleUid != nil { if p.ScribbleDate != nil && p.ScribbleUid != nil {
return errors.New("cannot scribble an already-scribbled post") return errors.New("cannot scribble an already-scribbled post")
} }
@@ -354,16 +342,12 @@ func (p *PostHeader) Scribble(ctx context.Context, u *User, comm *Community, ipa
p.Pseud = &scribblePseud p.Pseud = &scribblePseud
// Audit the operation. // Audit the operation.
ar = AmNewCommAudit(AuditConferenceScribbleMessage, u.Uid, comm.Id, ipaddr, fmt.Sprintf("post=%d", p.PostId)) AmStoreAudit(AmNewCommAudit(AuditConferenceScribbleMessage, u.Uid, comm.Id, ipaddr, fmt.Sprintf("post=%d", p.PostId)))
return nil return nil
} }
// Nuke causes a post to be nuked (deleted entirely from the topic). // Nuke causes a post to be nuked (deleted entirely from the topic).
func (p *PostHeader) Nuke(ctx context.Context, u *User, comm *Community, ipaddr string) error { func (p *PostHeader) Nuke(ctx context.Context, u *User, comm *Community, ipaddr string) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -414,7 +398,7 @@ func (p *PostHeader) Nuke(ctx context.Context, u *User, comm *Community, ipaddr
return err return err
} }
success = true success = true
ar = AmNewCommAudit(AuditConferenceNukeMessage, u.Uid, comm.Id, ipaddr, fmt.Sprintf("post=%d", p.PostId)) AmStoreAudit(AmNewCommAudit(AuditConferenceNukeMessage, u.Uid, comm.Id, ipaddr, fmt.Sprintf("post=%d", p.PostId)))
return nil return nil
} }
@@ -424,10 +408,6 @@ func (p *PostHeader) Publish(ctx context.Context, comm *Community, publisher *Us
return errors.New("cannot publish scribbled post") return errors.New("cannot publish scribbled post")
} }
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -455,7 +435,7 @@ func (p *PostHeader) Publish(ctx context.Context, comm *Community, publisher *Us
return err return err
} }
success = true success = true
ar = AmNewAudit(AuditPublishToFrontPage, publisher.Uid, ipaddr, fmt.Sprintf("comm=%d,post=%d", comm.Id, p.PostId)) AmStoreAudit(AmNewAudit(AuditPublishToFrontPage, publisher.Uid, ipaddr, fmt.Sprintf("comm=%d,post=%d", comm.Id, p.PostId)))
return nil return nil
} }
@@ -483,10 +463,6 @@ func (p *PostHeader) MoveTo(ctx context.Context, target *Topic, u *User, comm *C
return err return err
} }
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -548,8 +524,8 @@ func (p *PostHeader) MoveTo(ctx context.Context, target *Topic, u *User, comm *C
target.LastUpdate = lastUpdate target.LastUpdate = lastUpdate
// And audit the result. // And audit the result.
ar = AmNewCommAudit(AuditConferenceMoveMessage, u.Uid, comm.Id, ipaddr, fmt.Sprintf("conf=%d,post=%d", conf.ConfId, p.PostId), AmStoreAudit(AmNewCommAudit(AuditConferenceMoveMessage, u.Uid, comm.Id, ipaddr, fmt.Sprintf("conf=%d,post=%d", conf.ConfId, p.PostId),
fmt.Sprintf("fromTopic=%d", oldTopic.TopicId), fmt.Sprintf("toTopic=%d", target.TopicId)) fmt.Sprintf("fromTopic=%d", oldTopic.TopicId), fmt.Sprintf("toTopic=%d", target.TopicId)))
return nil return nil
} }
@@ -614,10 +590,6 @@ func AmGetPostRange(ctx context.Context, topic *Topic, first, last int32) ([]*Po
func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User, pseud string, post string, postLines int32, func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User, pseud string, post string, postLines int32,
comm *Community, ipaddr string) (*PostHeader, error) { comm *Community, ipaddr string) (*PostHeader, error) {
success := false success := false
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
if !success { if !success {
@@ -678,8 +650,8 @@ func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User,
success = true success = true
// create audit record // create audit record
ar = AmNewCommAudit(AuditConferencePostMessage, user.Uid, comm.Id, ipaddr, fmt.Sprintf("confid=%d", conf.ConfId), AmStoreAudit(AmNewCommAudit(AuditConferencePostMessage, user.Uid, comm.Id, ipaddr, fmt.Sprintf("confid=%d", conf.ConfId),
fmt.Sprintf("topic=%d", topic.Number), fmt.Sprintf("post=%d", hdr.PostId), fmt.Sprintf("pseud=%s", *hdr.Pseud)) fmt.Sprintf("topic=%d", topic.Number), fmt.Sprintf("post=%d", hdr.PostId), fmt.Sprintf("pseud=%s", *hdr.Pseud)))
return hdr, nil return hdr, nil
} }
+7 -27
View File
@@ -132,42 +132,30 @@ func (t *Topic) SetHidden(ctx context.Context, u *User, hidden bool) error {
// SetFrozen sets a topic's "frozen" state. // SetFrozen sets a topic's "frozen" state.
func (t *Topic) SetFrozen(ctx context.Context, frozen bool, u *User, comm *Community, ipaddr string) error { func (t *Topic) SetFrozen(ctx context.Context, frozen bool, u *User, comm *Community, ipaddr string) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
_, err := amdb.ExecContext(ctx, "UPDATE topics SET frozen = ? WHERE topicid = ?", frozen, t.TopicId) _, err := amdb.ExecContext(ctx, "UPDATE topics SET frozen = ? WHERE topicid = ?", frozen, t.TopicId)
if err == nil { if err == nil {
t.Frozen = frozen t.Frozen = frozen
ar = AmNewCommAudit(AuditConferenceFreezeTopic, u.Uid, comm.Id, ipaddr, fmt.Sprintf("topic=%d", t.TopicId), fmt.Sprintf("frozen=%t", frozen)) AmStoreAudit(AmNewCommAudit(AuditConferenceFreezeTopic, u.Uid, comm.Id, ipaddr, fmt.Sprintf("topic=%d", t.TopicId), fmt.Sprintf("frozen=%t", frozen)))
} }
return err return err
} }
// SetArchived sets a topic's "archived" state. // SetArchived sets a topic's "archived" state.
func (t *Topic) SetArchived(ctx context.Context, archived bool, u *User, comm *Community, ipaddr string) error { func (t *Topic) SetArchived(ctx context.Context, archived bool, u *User, comm *Community, ipaddr string) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
_, err := amdb.ExecContext(ctx, "UPDATE topics SET archived = ? WHERE topicid = ?", archived, t.TopicId) _, err := amdb.ExecContext(ctx, "UPDATE topics SET archived = ? WHERE topicid = ?", archived, t.TopicId)
if err == nil { if err == nil {
t.Archived = archived t.Archived = archived
ar = AmNewCommAudit(AuditConferenceArchiveTopic, u.Uid, comm.Id, ipaddr, fmt.Sprintf("topic=%d", t.TopicId), fmt.Sprintf("archived=%t", archived)) AmStoreAudit(AmNewCommAudit(AuditConferenceArchiveTopic, u.Uid, comm.Id, ipaddr, fmt.Sprintf("topic=%d", t.TopicId), fmt.Sprintf("archived=%t", archived)))
} }
return err return err
} }
// SetSticky sets a topic's "sticky" state. // SetSticky sets a topic's "sticky" state.
func (t *Topic) SetSticky(ctx context.Context, sticky bool, u *User, comm *Community, ipaddr string) error { func (t *Topic) SetSticky(ctx context.Context, sticky bool, u *User, comm *Community, ipaddr string) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
_, err := amdb.ExecContext(ctx, "UPDATE topics SET sticky = ? where topicid = ?", sticky, t.TopicId) _, err := amdb.ExecContext(ctx, "UPDATE topics SET sticky = ? where topicid = ?", sticky, t.TopicId)
if err == nil { if err == nil {
t.Sticky = sticky t.Sticky = sticky
ar = AmNewCommAudit(AuditConferenceStickyTopic, u.Uid, comm.Id, ipaddr, fmt.Sprintf("topic=%d", t.TopicId), fmt.Sprintf("sticky=%t", sticky)) AmStoreAudit(AmNewCommAudit(AuditConferenceStickyTopic, u.Uid, comm.Id, ipaddr, fmt.Sprintf("topic=%d", t.TopicId), fmt.Sprintf("sticky=%t", sticky)))
} }
return err return err
} }
@@ -441,10 +429,6 @@ func eraseTopicRecords(ctx context.Context, tx *sqlx.Tx, topicid int32) error {
// Delete deletes this topic. // Delete deletes this topic.
func (t *Topic) Delete(ctx context.Context, u *User, comm *Community, ipaddr string, background *util.WorkerPool) error { func (t *Topic) Delete(ctx context.Context, u *User, comm *Community, ipaddr string, background *util.WorkerPool) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -472,8 +456,8 @@ func (t *Topic) Delete(ctx context.Context, u *User, comm *Community, ipaddr str
success = true success = true
// create audit record // create audit record
ar = AmNewCommAudit(AuditConferenceDeleteTopic, u.Uid, comm.Id, ipaddr, fmt.Sprintf("confid=%d", conf.ConfId), AmStoreAudit(AmNewCommAudit(AuditConferenceDeleteTopic, u.Uid, comm.Id, ipaddr, fmt.Sprintf("confid=%d", conf.ConfId),
fmt.Sprintf("topic=%d", t.TopicId)) fmt.Sprintf("topic=%d", t.TopicId)))
// Spin off a background task to finish deleting this topic. // Spin off a background task to finish deleting this topic.
myTopicId := t.TopicId myTopicId := t.TopicId
@@ -748,10 +732,6 @@ func AmListTopics(ctx context.Context, confid int32, uid int32, viewOption int,
*/ */
func AmNewTopic(ctx context.Context, conf *Conference, user *User, title string, zeroPostPseud string, zeroPost string, func AmNewTopic(ctx context.Context, conf *Conference, user *User, title string, zeroPostPseud string, zeroPost string,
zeroPostLines int32, comm *Community, ipaddr string) (*Topic, error) { zeroPostLines int32, comm *Community, ipaddr string) (*Topic, error) {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -826,8 +806,8 @@ func AmNewTopic(ctx context.Context, conf *Conference, user *User, title string,
success = true success = true
// create audit record // create audit record
ar = AmNewCommAudit(AuditConferenceCreateTopic, user.Uid, comm.Id, ipaddr, fmt.Sprintf("confid=%d", conf.ConfId), AmStoreAudit(AmNewCommAudit(AuditConferenceCreateTopic, user.Uid, comm.Id, ipaddr, fmt.Sprintf("confid=%d", conf.ConfId),
fmt.Sprintf("num=%d", topic.Number), fmt.Sprintf("name=%s", topic.Name)) fmt.Sprintf("num=%d", topic.Number), fmt.Sprintf("name=%s", topic.Name)))
return topic, nil return topic, nil
} }
+25 -49
View File
@@ -250,11 +250,6 @@ func (u *User) NewAuthToken(ctx context.Context) (string, error) {
* Standard Go error status. * Standard Go error status.
*/ */
func (u *User) ConfirmEMailAddress(ctx context.Context, confnum int32, remoteIP string) error { func (u *User) ConfirmEMailAddress(ctx context.Context, confnum int32, remoteIP string) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
log.Debugf("ConfirmEMailAddress for UID %d", u.Uid) log.Debugf("ConfirmEMailAddress for UID %d", u.Uid)
u.Mutex.Lock() u.Mutex.Lock()
defer u.Mutex.Unlock() defer u.Mutex.Unlock()
@@ -264,7 +259,7 @@ func (u *User) ConfirmEMailAddress(ctx context.Context, confnum int32, remoteIP
} }
if confnum != u.EmailConfNum { if confnum != u.EmailConfNum {
log.Warn("...confirmation number incorrect") log.Warn("...confirmation number incorrect")
ar = AmNewAudit(AuditVerifyEmailFail, u.Uid, remoteIP, "Invalid confirmation number") AmStoreAudit(AmNewAudit(AuditVerifyEmailFail, u.Uid, remoteIP, "Invalid confirmation number"))
return errors.New("confirmation number is incorrect. Please try again") return errors.New("confirmation number is incorrect. Please try again")
} }
_, err := amdb.ExecContext(ctx, "UPDATE users SET verify_email = 1, base_lvl = ? WHERE uid = ?", _, err := amdb.ExecContext(ctx, "UPDATE users SET verify_email = 1, base_lvl = ? WHERE uid = ?",
@@ -273,7 +268,7 @@ func (u *User) ConfirmEMailAddress(ctx context.Context, confnum int32, remoteIP
u.VerifyEMail = true u.VerifyEMail = true
u.BaseLevel = AmDefaultRole("Global.AfterVerify").Level() u.BaseLevel = AmDefaultRole("Global.AfterVerify").Level()
if err = AmAutoJoinCommunities(ctx, u); err == nil { if err = AmAutoJoinCommunities(ctx, u); err == nil {
ar = AmNewAudit(AuditVerifyEmailOK, u.Uid, remoteIP) AmStoreAudit(AmNewAudit(AuditVerifyEmailOK, u.Uid, remoteIP))
} }
} }
return err return err
@@ -293,22 +288,19 @@ func (u *User) NewEmailConfirmationNumber(ctx context.Context) error {
// ChangePassword resets a user's password. // ChangePassword resets a user's password.
func (u *User) ChangePassword(ctx context.Context, password string, changer *User, remoteIP string) error { func (u *User) ChangePassword(ctx context.Context, password string, changer *User, remoteIP string) error {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
u.Mutex.Lock() u.Mutex.Lock()
defer u.Mutex.Unlock() defer u.Mutex.Unlock()
pval := hashPassword(password) pval := hashPassword(password)
_, err := amdb.ExecContext(ctx, "UPDATE users SET passhash = ? WHERE uid = ?", pval, u.Uid) _, err := amdb.ExecContext(ctx, "UPDATE users SET passhash = ? WHERE uid = ?", pval, u.Uid)
if err == nil { if err == nil {
u.Passhash = pval u.Passhash = pval
var arec *AuditRecord = nil
if changer.Uid == u.Uid { if changer.Uid == u.Uid {
ar = AmNewAudit(AuditChangePassword, u.Uid, remoteIP, "via password change request") arec = AmNewAudit(AuditChangePassword, u.Uid, remoteIP, "via password change request")
} else { } else {
ar = AmNewAudit(AuditAdminChangeUserPassword, changer.Uid, remoteIP, fmt.Sprintf("uid=%d", u.Uid)) arec = AmNewAudit(AuditAdminChangeUserPassword, changer.Uid, remoteIP, fmt.Sprintf("uid=%d", u.Uid))
} }
AmStoreAudit(arec)
} }
return err return err
} }
@@ -379,16 +371,11 @@ func (u *User) Prefs(ctx context.Context) (*UserPrefs, error) {
* Standard Go error status. * Standard Go error status.
*/ */
func (u *User) SetProfileData(ctx context.Context, reminder string, dob *time.Time, descr *string, setter *User, ipaddr string) error { func (u *User) SetProfileData(ctx context.Context, reminder string, dob *time.Time, descr *string, setter *User, ipaddr string) error {
ara := make([]*AuditRecord, 0, 3)
defer func() {
for _, ar := range ara {
AmStoreAudit(ar)
}
}()
u.Mutex.Lock() u.Mutex.Lock()
defer u.Mutex.Unlock() defer u.Mutex.Unlock()
_, err := amdb.ExecContext(ctx, "UPDATE users SET passreminder = ?, dob = ?, description = ? WHERE uid = ?", reminder, dob, descr, u.Uid) _, err := amdb.ExecContext(ctx, "UPDATE users SET passreminder = ?, dob = ?, description = ? WHERE uid = ?", reminder, dob, descr, u.Uid)
if err == nil { if err == nil {
ara := make([]*AuditRecord, 0, 3)
if setter.Uid != u.Uid { if setter.Uid != u.Uid {
if u.Description != descr { if u.Description != descr {
ara = append(ara, AmNewAudit(AuditAdminChangeUserAccount, setter.Uid, ipaddr, fmt.Sprintf("uid=%d", u.Uid), "field=description")) ara = append(ara, AmNewAudit(AuditAdminChangeUserAccount, setter.Uid, ipaddr, fmt.Sprintf("uid=%d", u.Uid), "field=description"))
@@ -400,18 +387,15 @@ func (u *User) SetProfileData(ctx context.Context, reminder string, dob *time.Ti
u.PassReminder = reminder u.PassReminder = reminder
u.DOB = dob u.DOB = dob
u.Description = descr u.Description = descr
for _, a := range ara {
AmStoreAudit(a)
}
} }
return err return err
} }
// SetSecurityData sets the "security" variables for this user. // SetSecurityData sets the "security" variables for this user.
func (u *User) SetSecurityData(ctx context.Context, baseLevel uint16, lockout, verifyEmail bool, setter *User, ipaddr string) error { func (u *User) SetSecurityData(ctx context.Context, baseLevel uint16, lockout, verifyEmail bool, setter *User, ipaddr string) error {
ara := make([]*AuditRecord, 0, 3)
defer func() {
for _, ar := range ara {
AmStoreAudit(ar)
}
}()
bofhLevel := AmRole("Global.BOFH").Level() bofhLevel := AmRole("Global.BOFH").Level()
if (u.BaseLevel == bofhLevel || baseLevel == bofhLevel) && u.BaseLevel != baseLevel { if (u.BaseLevel == bofhLevel || baseLevel == bofhLevel) && u.BaseLevel != baseLevel {
return errors.New("cannot change levels to or from global system administrator") return errors.New("cannot change levels to or from global system administrator")
@@ -420,6 +404,7 @@ func (u *User) SetSecurityData(ctx context.Context, baseLevel uint16, lockout, v
defer u.Mutex.Unlock() defer u.Mutex.Unlock()
_, err := amdb.ExecContext(ctx, "UPDATE users SET base_lvl = ?, lockout = ?, verify_email = ? WHERE uid = ?", baseLevel, lockout, verifyEmail, u.Uid) _, err := amdb.ExecContext(ctx, "UPDATE users SET base_lvl = ?, lockout = ?, verify_email = ? WHERE uid = ?", baseLevel, lockout, verifyEmail, u.Uid)
if err == nil { if err == nil {
ara := make([]*AuditRecord, 0, 3)
if u.BaseLevel != baseLevel { if u.BaseLevel != baseLevel {
ara = append(ara, AmNewAudit(AuditAdminSetAccountSecurity, setter.Uid, ipaddr, fmt.Sprintf("uid=%d", u.Uid), fmt.Sprintf("level=%d", baseLevel))) ara = append(ara, AmNewAudit(AuditAdminSetAccountSecurity, setter.Uid, ipaddr, fmt.Sprintf("uid=%d", u.Uid), fmt.Sprintf("level=%d", baseLevel)))
} }
@@ -438,6 +423,9 @@ func (u *User) SetSecurityData(ctx context.Context, baseLevel uint16, lockout, v
u.BaseLevel = baseLevel u.BaseLevel = baseLevel
u.Lockout = lockout u.Lockout = lockout
u.VerifyEMail = verifyEmail u.VerifyEMail = verifyEmail
for _, a := range ara {
AmStoreAudit(a)
}
} }
return err return err
} }
@@ -605,10 +593,6 @@ func touchUser(ctx context.Context, tx *sqlx.Tx, user *User) {
*/ */
func AmAuthenticateUser(ctx context.Context, name string, password string, remoteIP string) (*User, error) { func AmAuthenticateUser(ctx context.Context, name string, password string, remoteIP string) (*User, error) {
log.Debugf("AmAuthenticateUser() authenticating user %s...", name) log.Debugf("AmAuthenticateUser() authenticating user %s...", name)
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -620,17 +604,17 @@ func AmAuthenticateUser(ctx context.Context, name string, password string, remot
user, err := AmGetUserByName(ctx, name, tx) user, err := AmGetUserByName(ctx, name, tx)
if err != nil { if err != nil {
log.Error("...user not found") log.Error("...user not found")
ar = AmNewAudit(AuditLoginFail, 0, remoteIP, fmt.Sprintf("Bad username: %s", name)) AmStoreAudit(AmNewAudit(AuditLoginFail, 0, remoteIP, fmt.Sprintf("Bad username: %s", name)))
return nil, errors.New("the user account you have specified does not exist; please try again") return nil, errors.New("the user account you have specified does not exist; please try again")
} }
if user.IsAnon { if user.IsAnon {
log.Error("...user is the Anonymous Honyak, can't explicitly log in") log.Error("...user is the Anonymous Honyak, can't explicitly log in")
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Anonymous user") AmStoreAudit(AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Anonymous user"))
return nil, errors.New("this account cannot be explicitly logged into; please try again") return nil, errors.New("this account cannot be explicitly logged into; please try again")
} }
if user.Lockout { if user.Lockout {
log.Error("...user is locked out by the admin") log.Error("...user is locked out by the admin")
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Account locked out") AmStoreAudit(AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Account locked out"))
return nil, errors.New("this account has been administratively locked; please contact the system administrator for assistance") return nil, errors.New("this account has been administratively locked; please contact the system administrator for assistance")
} }
passok := false passok := false
@@ -642,7 +626,7 @@ func AmAuthenticateUser(ctx context.Context, name string, password string, remot
} }
if !passok { if !passok {
log.Warn("...invalid password") log.Warn("...invalid password")
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Bad password") AmStoreAudit(AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Bad password"))
return nil, errors.New("the password you have specified is incorrect; please try again") return nil, errors.New("the password you have specified is incorrect; please try again")
} }
log.Debug("...authenticated") log.Debug("...authenticated")
@@ -651,7 +635,7 @@ func AmAuthenticateUser(ctx context.Context, name string, password string, remot
return nil, err return nil, err
} }
success = true success = true
ar = AmNewAudit(AuditLoginOK, user.Uid, remoteIP) AmStoreAudit(AmNewAudit(AuditLoginOK, user.Uid, remoteIP))
return user, nil return user, nil
} }
@@ -689,10 +673,6 @@ func crackAuthString(authString string) (int32, string, error) {
* Standard Go error status. * Standard Go error status.
*/ */
func AmAuthenticateUserByToken(ctx context.Context, authString string, remoteIP string) (*User, error) { func AmAuthenticateUserByToken(ctx context.Context, authString string, remoteIP string) (*User, error) {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -709,23 +689,23 @@ func AmAuthenticateUserByToken(ctx context.Context, authString string, remoteIP
user, err = AmGetUserTx(ctx, tx, uid) user, err = AmGetUserTx(ctx, tx, uid)
if err != nil { if err != nil {
log.Error("...user not found") log.Error("...user not found")
ar = AmNewAudit(AuditLoginFail, 0, remoteIP, fmt.Sprintf("Bad uid: %d", uid)) AmStoreAudit(AmNewAudit(AuditLoginFail, 0, remoteIP, fmt.Sprintf("Bad uid: %d", uid)))
return nil, fmt.Errorf("uid %d not found, ignore: %v", uid, err) return nil, fmt.Errorf("uid %d not found, ignore: %v", uid, err)
} }
log.Debugf("AmAuthenicateUserByToken() authenticating user %d...", uid) log.Debugf("AmAuthenicateUserByToken() authenticating user %d...", uid)
if user.IsAnon { if user.IsAnon {
log.Error("...user is the Anonymous Honyak, can't explicitly log in") log.Error("...user is the Anonymous Honyak, can't explicitly log in")
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Anonymous user") AmStoreAudit(AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Anonymous user"))
return nil, errors.New("this account cannot be explicitly logged into; please try again") return nil, errors.New("this account cannot be explicitly logged into; please try again")
} }
if user.Lockout { if user.Lockout {
log.Error("...user is locked out by the admin") log.Error("...user is locked out by the admin")
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Account locked out") AmStoreAudit(AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Account locked out"))
return nil, errors.New("this account has been administratively locked; please contact the system administrator for assistance") return nil, errors.New("this account has been administratively locked; please contact the system administrator for assistance")
} }
if user.Tokenauth == nil || *(user.Tokenauth) != token { if user.Tokenauth == nil || *(user.Tokenauth) != token {
log.Error("...token mismatch") log.Error("...token mismatch")
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Token mismatch") AmStoreAudit(AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Token mismatch"))
return nil, errors.New("token mismatch") return nil, errors.New("token mismatch")
} }
log.Debug("...authenticated") log.Debug("...authenticated")
@@ -734,7 +714,7 @@ func AmAuthenticateUserByToken(ctx context.Context, authString string, remoteIP
return nil, err return nil, err
} }
success = true success = true
ar = AmNewAudit(AuditLoginOK, user.Uid, remoteIP) AmStoreAudit(AmNewAudit(AuditLoginOK, user.Uid, remoteIP))
return user, nil return user, nil
} }
@@ -751,10 +731,6 @@ func AmAuthenticateUserByToken(ctx context.Context, authString string, remoteIP
* Standard Go error status. * Standard Go error status.
*/ */
func AmCreateNewUser(ctx context.Context, username string, password string, reminder string, dob *time.Time, remoteIP string) (*User, error) { func AmCreateNewUser(ctx context.Context, username string, password string, reminder string, dob *time.Time, remoteIP string) (*User, error) {
var ar *AuditRecord = nil
defer func() {
AmStoreAudit(ar)
}()
anon, _ := AmGetAnonUser(ctx) anon, _ := AmGetAnonUser(ctx)
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
@@ -827,7 +803,7 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi
} }
// operation was a success - add an audit record // operation was a success - add an audit record
ar = AmNewAudit(AuditAccountCreated, user.Uid, remoteIP) AmStoreAudit(AmNewAudit(AuditAccountCreated, user.Uid, remoteIP))
return user, nil return user, nil
} }