all database operations now take a context.Context, which is propagated through from sources
This commit is contained in:
+13
-13
@@ -32,22 +32,22 @@ import (
|
||||
*/
|
||||
func ShowCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
me := ctxt.CurrentUser()
|
||||
prefs, err := me.Prefs()
|
||||
prefs, err := me.Prefs(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
comm := ctxt.CurrentCommunity() // set by middleware
|
||||
ci, err := comm.ContactInfo()
|
||||
ci, err := comm.ContactInfo(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
host, err := comm.Host()
|
||||
host, err := comm.Host(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
var cats []*database.Category
|
||||
if !ctxt.GlobalFlags().Get(database.GlobalFlagNoCategories) {
|
||||
cats, err = database.AmGetCategoryHierarchy(comm.CategoryId)
|
||||
cats, err = database.AmGetCategoryHierarchy(ctxt.Ctx(), comm.CategoryId)
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func ShowCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
func JoinCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
me := ctxt.CurrentUser()
|
||||
comm := ctxt.CurrentCommunity() // set by middleware
|
||||
mbr, _, _, err := comm.Membership(me)
|
||||
mbr, _, _, err := comm.Membership(ctxt.Ctx(), me)
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func JoinCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
return dlg.Render(ctxt)
|
||||
}
|
||||
// if get here, this is a public community, and we can join
|
||||
err = comm.SetMembership(me, database.AmDefaultRole("Community.NewUser").Level(), false, me.Uid, ctxt.RemoteIP())
|
||||
err = comm.SetMembership(ctxt.Ctx(), me, database.AmDefaultRole("Community.NewUser").Level(), false, me.Uid, ctxt.RemoteIP())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -182,7 +182,7 @@ func JoinCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
func JoinCommunityWithKey(ctxt ui.AmContext) (string, any, error) {
|
||||
me := ctxt.CurrentUser()
|
||||
comm := ctxt.CurrentCommunity() // set by middleware
|
||||
mbr, _, _, err := comm.Membership(me)
|
||||
mbr, _, _, err := comm.Membership(ctxt.Ctx(), me)
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -210,7 +210,7 @@ func JoinCommunityWithKey(ctxt ui.AmContext) (string, any, error) {
|
||||
if comm.JoinKey != nil && key != *comm.JoinKey {
|
||||
return dlg.RenderError(ctxt, "The join key does not match the community. Please try again.")
|
||||
}
|
||||
err = comm.SetMembership(me, database.AmDefaultRole("Community.NewUser").Level(), false, me.Uid, ctxt.RemoteIP())
|
||||
err = comm.SetMembership(ctxt.Ctx(), me, database.AmDefaultRole("Community.NewUser").Level(), false, me.Uid, ctxt.RemoteIP())
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, fmt.Sprintf("Error joining: %v", err))
|
||||
}
|
||||
@@ -232,7 +232,7 @@ func JoinCommunityWithKey(ctxt ui.AmContext) (string, any, error) {
|
||||
func UnjoinCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
me := ctxt.CurrentUser()
|
||||
comm := ctxt.CurrentCommunity() // set by middleware
|
||||
mbr, lock, _, err := comm.Membership(me)
|
||||
mbr, lock, _, err := comm.Membership(ctxt.Ctx(), me)
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -260,7 +260,7 @@ func UnjoinCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
func UnjoinCommunityConfirm(ctxt ui.AmContext) (string, any, error) {
|
||||
me := ctxt.CurrentUser()
|
||||
comm := ctxt.CurrentCommunity() // set by middleware
|
||||
mbr, lock, _, err := comm.Membership(me)
|
||||
mbr, lock, _, err := comm.Membership(ctxt.Ctx(), me)
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -276,7 +276,7 @@ func UnjoinCommunityConfirm(ctxt ui.AmContext) (string, any, error) {
|
||||
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
|
||||
}
|
||||
if ctxt.FormFieldIsSet("unjoin") {
|
||||
err = comm.SetMembership(me, 0, false, me.Uid, ctxt.RemoteIP())
|
||||
err = comm.SetMembership(ctxt.Ctx(), me, 0, false, me.Uid, ctxt.RemoteIP())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -314,7 +314,7 @@ func MemberList(ctxt ui.AmContext) (string, any, error) {
|
||||
ctxt.VarMap().Set("ofs", ofs)
|
||||
ctxt.VarMap().Set("amsterdam_pageTitle", "List Members")
|
||||
listMax := int(ctxt.Globals().MaxCommunityMemberPage)
|
||||
results, total, err := comm.ListMembers(database.ListMembersFieldNone, database.ListMembersOperNone, "", ofs*listMax, listMax, showHidden)
|
||||
results, total, err := comm.ListMembers(ctxt.Ctx(), database.ListMembersFieldNone, database.ListMembersOperNone, "", ofs*listMax, listMax, showHidden)
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -385,7 +385,7 @@ func MemberSearch(ctxt ui.AmContext) (string, any, error) {
|
||||
return "framed_template", "memberlist.jet", nil
|
||||
}
|
||||
listMax := int(ctxt.Globals().MaxCommunityMemberPage)
|
||||
results, total, err := comm.ListMembers(iField, iOper, term, ofs*listMax, listMax, showHidden)
|
||||
results, total, err := comm.ListMembers(ctxt.Ctx(), iField, iOper, term, ofs*listMax, listMax, showHidden)
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
|
||||
+20
-20
@@ -88,11 +88,11 @@ func CommunityProfileForm(ctxt ui.AmContext) (string, any, error) {
|
||||
return ui.ErrorPage(ctxt, errors.New("you are not permitted to access this page"))
|
||||
}
|
||||
var ci *database.ContactInfo
|
||||
ci, err := comm.ContactInfo()
|
||||
ci, err := comm.ContactInfo(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
flags, err := comm.Flags()
|
||||
flags, err := comm.Flags(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -184,12 +184,12 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
var ci *database.ContactInfo
|
||||
ci, err = comm.ContactInfo()
|
||||
ci, err = comm.ContactInfo(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
var flags *util.OptionSet
|
||||
flags, err = comm.Flags()
|
||||
flags, err = comm.Flags(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -202,7 +202,7 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
|
||||
nci.Region = dlg.Field("reg").ValPtr()
|
||||
nci.PostalCode = dlg.Field("pcode").ValPtr()
|
||||
nci.Country = dlg.Field("country").ValPtr()
|
||||
_, err = nci.Save()
|
||||
_, err = nci.Save(ctxt.Ctx())
|
||||
ci = nci
|
||||
if err == nil {
|
||||
var joinkey *string = nil
|
||||
@@ -221,17 +221,17 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
|
||||
hidedir = true
|
||||
hidesearch = true
|
||||
}
|
||||
err = comm.SetProfileData(dlg.Field("name").Value, dlg.Field("alias").Value, dlg.Field("synopsis").ValPtr(),
|
||||
err = comm.SetProfileData(ctxt.Ctx(), dlg.Field("name").Value, dlg.Field("alias").Value, dlg.Field("synopsis").ValPtr(),
|
||||
dlg.Field("rules").ValPtr(), dlg.Field("language").ValPtr(), joinkey, dlg.Field("membersonly").IsChecked(),
|
||||
hidedir, hidesearch, dlg.Field("read_lvl").GetLevel(), dlg.Field("write_lvl").GetLevel(),
|
||||
dlg.Field("create_lvl").GetLevel(), dlg.Field("delete_lvl").GetLevel(), dlg.Field("join_lvl").GetLevel())
|
||||
}
|
||||
if err == nil {
|
||||
flags.Set(database.CommunityFlagPicturesInPosts, dlg.Field("pic_in_post").IsChecked())
|
||||
err = comm.SaveFlags(flags)
|
||||
err = comm.SaveFlags(ctxt.Ctx(), flags)
|
||||
}
|
||||
if err == nil {
|
||||
err = comm.TouchUpdate()
|
||||
err = comm.TouchUpdate(ctxt.Ctx())
|
||||
}
|
||||
if err != nil {
|
||||
ctxt.ClearCommunityContext()
|
||||
@@ -259,7 +259,7 @@ func CommunityLogoForm(ctxt ui.AmContext) (string, any, error) {
|
||||
ctxt.SetRC(http.StatusForbidden)
|
||||
return ui.ErrorPage(ctxt, errors.New("you are not permitted to access this page"))
|
||||
}
|
||||
ci, err := comm.ContactInfo()
|
||||
ci, err := comm.ContactInfo(ctxt.Ctx())
|
||||
if err == nil {
|
||||
ctxt.VarMap().Set("commName", comm.Name)
|
||||
ctxt.VarMap().Set("commAlias", comm.Alias)
|
||||
@@ -284,7 +284,7 @@ func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
|
||||
ctxt.SetRC(http.StatusForbidden)
|
||||
return ui.ErrorPage(ctxt, errors.New("you are not permitted to access this page"))
|
||||
}
|
||||
ci, err := comm.ContactInfo()
|
||||
ci, err := comm.ContactInfo(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -300,13 +300,13 @@ func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
|
||||
ui.CommunityLogoMaxBytes)
|
||||
if err == nil {
|
||||
var img *database.ImageStore
|
||||
img, err = database.AmStoreImage(database.ImageTypeCommunityLogo, comm.Id, mimeType, imageData)
|
||||
img, err = database.AmStoreImage(ctxt.Ctx(), database.ImageTypeCommunityLogo, comm.Id, mimeType, imageData)
|
||||
if err == nil {
|
||||
photourl := fmt.Sprintf("/img/store/%d", img.ImgId)
|
||||
ci.PhotoURL = &photourl
|
||||
_, err = ci.Save()
|
||||
_, err = ci.Save(ctxt.Ctx())
|
||||
if err == nil {
|
||||
err = comm.TouchUpdate()
|
||||
err = comm.TouchUpdate(ctxt.Ctx())
|
||||
}
|
||||
if err == nil {
|
||||
return "redirect", "/comm/" + comm.Alias + "/admin/profile", nil
|
||||
@@ -336,7 +336,7 @@ func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
|
||||
defer func() {
|
||||
if happy {
|
||||
ampool.Submit(func(context.Context) {
|
||||
err := database.AmDeleteImage(int32(id))
|
||||
err := database.AmDeleteImage(ctxt.Ctx(), int32(id))
|
||||
if err != nil {
|
||||
log.Errorf("unable to delete image ID %d: %v", id, err)
|
||||
}
|
||||
@@ -345,7 +345,7 @@ func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
|
||||
}()
|
||||
}
|
||||
ci.PhotoURL = nil
|
||||
_, err := ci.Save()
|
||||
_, err := ci.Save(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -409,7 +409,7 @@ func CreateCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
var testcomm *database.Community
|
||||
testcomm, err = database.AmGetCommunityByAlias(dlg.Field("alias").Value)
|
||||
testcomm, err = database.AmGetCommunityByAlias(ctxt.Ctx(), dlg.Field("alias").Value)
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
@@ -429,7 +429,7 @@ func CreateCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
hideSearch = true
|
||||
}
|
||||
var comm *database.Community
|
||||
comm, err = database.AmCreateCommunity(dlg.Field("name").Value, dlg.Field("alias").Value, user.Uid,
|
||||
comm, err = database.AmCreateCommunity(ctxt.Ctx(), dlg.Field("name").Value, dlg.Field("alias").Value, user.Uid,
|
||||
dlg.Field("language").ValPtr(), dlg.Field("synopsis").ValPtr(), dlg.Field("rules").ValPtr(),
|
||||
dlg.Field("joinkey").ValPtr(), hideDir, hideSearch, ctxt.RemoteIP())
|
||||
if err != nil {
|
||||
@@ -440,12 +440,12 @@ func CreateCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
ci.Region = dlg.Field("reg").ValPtr()
|
||||
ci.PostalCode = dlg.Field("pcode").ValPtr()
|
||||
ci.Country = dlg.Field("country").ValPtr()
|
||||
_, err = ci.Save()
|
||||
_, err = ci.Save(ctxt.Ctx())
|
||||
if err == nil {
|
||||
err = comm.SetContactID(ci.ContactId)
|
||||
err = comm.SetContactID(ctxt.Ctx(), ci.ContactId)
|
||||
}
|
||||
if err == nil {
|
||||
err = comm.TouchUpdate()
|
||||
err = comm.TouchUpdate(ctxt.Ctx())
|
||||
}
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
|
||||
+28
-26
@@ -41,7 +41,7 @@ func Conferences(ctxt ui.AmContext) (string, any, error) {
|
||||
ctxt.VarMap().Set("commName", comm.Name)
|
||||
ctxt.VarMap().Set("commAlias", comm.Alias)
|
||||
ctxt.VarMap().Set("amsterdam_pageTitle", "Conference Listing: "+comm.Name)
|
||||
clist, err := database.AmGetCommunityConferences(comm.Id,
|
||||
clist, err := database.AmGetCommunityConferences(ctxt.Ctx(), comm.Id,
|
||||
comm.TestPermission("Community.ShowHiddenObjects", ctxt.EffectiveLevel()))
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
@@ -59,7 +59,7 @@ func Conferences(ctxt ui.AmContext) (string, any, error) {
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func Topics(ctxt ui.AmContext) (string, any, error) {
|
||||
prefs, err := ctxt.CurrentUser().Prefs()
|
||||
prefs, err := ctxt.CurrentUser().Prefs(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -94,7 +94,7 @@ func Topics(ctxt ui.AmContext) (string, any, error) {
|
||||
sort = ctxt.QueryParamInt("sort", sort)
|
||||
ctxt.SetSession("topic.sort", sort)
|
||||
|
||||
topics, err := database.AmListTopics(conf.ConfId, ctxt.CurrentUserId(), view, sort, false)
|
||||
topics, err := database.AmListTopics(ctxt.Ctx(), conf.ConfId, ctxt.CurrentUserId(), view, sort, false)
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -137,12 +137,12 @@ func NewTopicForm(ctxt ui.AmContext) (string, any, error) {
|
||||
ctxt.VarMap().Set("conferenceName", conf.Name)
|
||||
ctxt.VarMap().Set("urlStem", fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, ctxt.URLParam("confid")))
|
||||
ctxt.VarMap().Set("topicName", "")
|
||||
cs, err := conf.Settings(ctxt.CurrentUser())
|
||||
cs, err := conf.Settings(ctxt.Ctx(), ctxt.CurrentUser())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
if cs == nil || cs.DefaultPseud == nil {
|
||||
ci, err := ctxt.CurrentUser().ContactInfo()
|
||||
ci, err := ctxt.CurrentUser().ContactInfo(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
if ctxt.FormFieldIsSet("preview") {
|
||||
// start by escaping the title
|
||||
checker, err := htmlcheck.AmNewHTMLChecker("escaper")
|
||||
checker, err := htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "escaper")
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -203,7 +203,7 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
|
||||
ctxt.VarMap().Set("pb", v)
|
||||
|
||||
// run the preview
|
||||
checker, err = htmlcheck.AmNewHTMLChecker("preview")
|
||||
checker, err = htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "preview")
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -225,7 +225,7 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
if ctxt.FormFieldIsSet("post1") {
|
||||
// start by checking the title and pseud
|
||||
checker, err := htmlcheck.AmNewHTMLChecker("post-pseud")
|
||||
checker, err := htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "post-pseud")
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -238,7 +238,7 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
|
||||
zeroPostPseud, _ := checker.Value()
|
||||
|
||||
// now check the post data itself
|
||||
checker, err = htmlcheck.AmNewHTMLChecker("post-body")
|
||||
checker, err = htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "post-body")
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -249,7 +249,7 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
|
||||
lines, _ := checker.Lines()
|
||||
|
||||
// Add the topic!
|
||||
topic, err := database.AmNewTopic(conf, ctxt.CurrentUser(), topicName, zeroPostPseud, zeroPost, int32(lines), ctxt.RemoteIP())
|
||||
topic, err := database.AmNewTopic(ctxt.Ctx(), conf, ctxt.CurrentUser(), topicName, zeroPostPseud, zeroPost, int32(lines), ctxt.RemoteIP())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -258,7 +258,7 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
|
||||
return "redirect", urlStem, nil // no attachment - just redisplay topic list
|
||||
}
|
||||
|
||||
post, err := topic.GetPost(0) // get the initial post in the new topic
|
||||
post, err := topic.GetPost(ctxt.Ctx(), 0) // get the initial post in the new topic
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -303,12 +303,12 @@ func AttachmentUpload(ctxt ui.AmContext) (string, any, error) {
|
||||
if err == nil {
|
||||
if file.Size <= (1024 * 1024) { // 1 Mb
|
||||
var post *database.PostHeader
|
||||
post, err = database.AmGetPost(postId)
|
||||
post, err = database.AmGetPost(ctxt.Ctx(), postId)
|
||||
if err == nil {
|
||||
var data []byte
|
||||
data, err = slurpFile(file)
|
||||
if err == nil {
|
||||
err = post.SetAttachment(file.Filename, file.Header.Get("Content-Type"), int32(file.Size), data)
|
||||
err = post.SetAttachment(ctxt.Ctx(), file.Filename, file.Header.Get("Content-Type"), int32(file.Size), data)
|
||||
if err == nil {
|
||||
return "redirect", target, nil
|
||||
}
|
||||
@@ -370,7 +370,8 @@ func breakRange(topic *database.Topic, into []int32, param string, sep string) e
|
||||
func templateExtractUserName(args jet.Arguments) reflect.Value {
|
||||
rc := "<<ERROR>>"
|
||||
post := args.Get(0).Convert(reflect.TypeFor[*database.PostHeader]()).Interface().(*database.PostHeader)
|
||||
user, err := database.AmGetUser(post.CreatorUid)
|
||||
ctxt := args.Get(1).Convert(reflect.TypeFor[ui.AmContext]()).Interface().(ui.AmContext)
|
||||
user, err := database.AmGetUser(ctxt.Ctx(), post.CreatorUid)
|
||||
if err == nil {
|
||||
rc = user.Username
|
||||
} else {
|
||||
@@ -381,7 +382,8 @@ func templateExtractUserName(args jet.Arguments) reflect.Value {
|
||||
|
||||
func templatePostText(args jet.Arguments) reflect.Value {
|
||||
post := args.Get(0).Convert(reflect.TypeFor[*database.PostHeader]()).Interface().(*database.PostHeader)
|
||||
rc, err := post.Text()
|
||||
ctxt := args.Get(1).Convert(reflect.TypeFor[ui.AmContext]()).Interface().(ui.AmContext)
|
||||
rc, err := post.Text(ctxt.Ctx())
|
||||
if err != nil {
|
||||
log.Errorf("templatePostText could not get post text from post #%d: %v", post.PostId, err)
|
||||
rc = ""
|
||||
@@ -395,10 +397,10 @@ func templateOverrideLine(args jet.Arguments) reflect.Value {
|
||||
rc := ""
|
||||
if post.IsScribbled() {
|
||||
scr_date := ""
|
||||
scr_user, err := database.AmGetUser(*post.ScribbleUid)
|
||||
scr_user, err := database.AmGetUser(ctxt.Ctx(), *post.ScribbleUid)
|
||||
if err == nil {
|
||||
var p *database.UserPrefs
|
||||
p, err = ctxt.CurrentUser().Prefs()
|
||||
p, err = ctxt.CurrentUser().Prefs(ctxt.Ctx())
|
||||
if err == nil {
|
||||
scr_date = p.Localizer().Strftime("%b %e, %Y %r", *post.ScribbleDate)
|
||||
}
|
||||
@@ -430,20 +432,20 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
|
||||
rst := strings.Split(ctxt.Parameter("rst"), ",")
|
||||
if len(rst) >= 2 {
|
||||
user := ctxt.CurrentUser()
|
||||
ampool.Submit(func(context.Context) {
|
||||
ampool.Submit(func(ctx context.Context) {
|
||||
topicId, e1 := strconv.ParseInt(rst[0], 10, 32)
|
||||
lastRead, e2 := strconv.ParseInt(rst[1], 10, 32)
|
||||
if e1 == nil && e2 == nil {
|
||||
topic, _ := database.AmGetTopic(int32(topicId))
|
||||
topic, _ := database.AmGetTopic(ctx, int32(topicId))
|
||||
if topic != nil {
|
||||
topic.SetLastRead(user, int32(lastRead))
|
||||
topic.SetLastRead(ctx, user, int32(lastRead))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// Get user prefs.
|
||||
prefs, err := ctxt.CurrentUser().Prefs()
|
||||
prefs, err := ctxt.CurrentUser().Prefs(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -452,7 +454,7 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
|
||||
conf := ctxt.GetScratch("currentConference").(*database.Conference)
|
||||
var topic *database.Topic = nil
|
||||
if rawTopic, err := strconv.ParseInt(ctxt.URLParam("topic"), 10, 16); err == nil {
|
||||
topic, err = database.AmGetTopicByNumber(conf, int16(rawTopic))
|
||||
topic, err = database.AmGetTopicByNumber(ctxt.Ctx(), conf, int16(rawTopic))
|
||||
}
|
||||
if topic == nil {
|
||||
ctxt.SetRC(http.StatusNotFound)
|
||||
@@ -460,7 +462,7 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
|
||||
// Determine the range of posts to display. The "pin" is the post number after which we display the horizontal line separating old and new posts.
|
||||
lastRead, err := topic.GetLastRead(ctxt.CurrentUser())
|
||||
lastRead, err := topic.GetLastRead(ctxt.Ctx(), ctxt.CurrentUser())
|
||||
if err != nil {
|
||||
ctxt.SetRC(http.StatusNotFound)
|
||||
return ui.ErrorPage(ctxt, fmt.Errorf("posts not found in topic %d - %v", topic.Number, err))
|
||||
@@ -495,7 +497,7 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
|
||||
// Load the actual posts.
|
||||
posts, err := database.AmGetPostRange(topic, postRange[0], postRange[1])
|
||||
posts, err := database.AmGetPostRange(ctxt.Ctx(), topic, postRange[0], postRange[1])
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, fmt.Errorf("internal error getting posts <%d:%d-%d> - %v", topic.Number, postRange[0], postRange[1], err))
|
||||
}
|
||||
@@ -533,8 +535,8 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
|
||||
ctxt.VarMap().Set("amsterdam_pageTitle", fmt.Sprintf("%s: %s", topic.Name, summaryLine))
|
||||
if resetLastRead {
|
||||
user := ctxt.CurrentUser()
|
||||
ampool.Submit(func(context.Context) {
|
||||
topic.SetLastRead(user, topic.TopMessage)
|
||||
ampool.Submit(func(ctx context.Context) {
|
||||
topic.SetLastRead(ctx, user, topic.TopMessage)
|
||||
})
|
||||
}
|
||||
return "framed_template", "posts.jet", nil
|
||||
|
||||
+4
-3
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -113,12 +114,12 @@ func AmNewAudit(rectype int32, uid int32, ip string, data ...string) *AuditRecor
|
||||
}
|
||||
|
||||
// Store stores the audit record in the database.
|
||||
func (ar *AuditRecord) Store() error {
|
||||
func (ar *AuditRecord) Store(ctx context.Context) error {
|
||||
if ar.Record > 0 {
|
||||
return fmt.Errorf("audit record %d already stored", ar.Record)
|
||||
}
|
||||
moment := time.Now().UTC()
|
||||
rs, err := amdb.Exec(`INSERT INTO audit (on_date, event, uid, commid, ip, data1, data2, data3, data4)
|
||||
rs, err := amdb.ExecContext(ctx, `INSERT INTO audit (on_date, event, uid, commid, ip, data1, data2, data3, data4)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);`, moment, ar.Event, ar.Uid, ar.CommId, ar.IP,
|
||||
ar.Data1, ar.Data2, ar.Data3, ar.Data4)
|
||||
if err != nil {
|
||||
@@ -132,7 +133,7 @@ func (ar *AuditRecord) Store() error {
|
||||
// auditWriter is the routine that stores audit records in trhe background.
|
||||
func auditWriter(workChan chan *AuditRecord, doneChan chan bool) {
|
||||
for ar := range workChan {
|
||||
err := ar.Store()
|
||||
err := ar.Store(context.Background())
|
||||
if err != nil {
|
||||
log.Errorf("dropped audit record (%+v) on the floor: %v", *ar, err)
|
||||
}
|
||||
|
||||
+26
-21
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"slices"
|
||||
"strings"
|
||||
@@ -45,12 +46,12 @@ var categoryIdMap map[int32]*Category = make(map[int32]*Category)
|
||||
var categoryMutex sync.Mutex
|
||||
|
||||
// isCatEnabled determines if category features are enabled.
|
||||
func isCatEnabled() (bool, error) {
|
||||
g, err := AmGlobals()
|
||||
func isCatEnabled(ctx context.Context) (bool, error) {
|
||||
g, err := AmGlobals(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
set, err := g.Flags()
|
||||
set, err := g.Flags(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -58,11 +59,11 @@ func isCatEnabled() (bool, error) {
|
||||
}
|
||||
|
||||
// loadCategories loads the categories list from the database.
|
||||
func loadCategories() error {
|
||||
func loadCategories(ctx context.Context) error {
|
||||
categoryMutex.Lock()
|
||||
defer categoryMutex.Unlock()
|
||||
if allCategories == nil {
|
||||
rs, err := amdb.Query("SELECT COUNT(*) FROM refcategory")
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT COUNT(*) FROM refcategory")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -72,7 +73,7 @@ func loadCategories() error {
|
||||
var ncats int32
|
||||
rs.Scan(&ncats)
|
||||
allCategories = make([]Category, 0, ncats)
|
||||
err = amdb.Select(&allCategories, "SELECT * FROM refcategory ORDER BY parent, name")
|
||||
err = amdb.SelectContext(ctx, &allCategories, "SELECT * FROM refcategory ORDER BY parent, name")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -85,20 +86,21 @@ func loadCategories() error {
|
||||
|
||||
/* AmGetCategory returns the category for the given name.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* catid - The ID of the category to get.
|
||||
* Returns:
|
||||
* Pointer to the appropriate Category, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetCategory(catid int32) (*Category, error) {
|
||||
ok, err := isCatEnabled()
|
||||
func AmGetCategory(ctx context.Context, catid int32) (*Category, error) {
|
||||
ok, err := isCatEnabled(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return nil, errors.New("category feature not supported")
|
||||
}
|
||||
err = loadCategories()
|
||||
err = loadCategories(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -116,20 +118,21 @@ func AmGetCategory(catid int32) (*Category, error) {
|
||||
|
||||
/* AmGetCategoryHierarchy returns the category hierarchy for the given ID.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* catid - The ID of the category to get.
|
||||
* Returns:
|
||||
* Array of pointers to the categories in hierarchical order, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetCategoryHierarchy(catid int32) ([]*Category, error) {
|
||||
ok, err := isCatEnabled()
|
||||
func AmGetCategoryHierarchy(ctx context.Context, catid int32) ([]*Category, error) {
|
||||
ok, err := isCatEnabled(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return nil, errors.New("category feature not supported")
|
||||
}
|
||||
err = loadCategories()
|
||||
err = loadCategories(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -154,20 +157,21 @@ func AmGetCategoryHierarchy(catid int32) ([]*Category, error) {
|
||||
|
||||
/* AmGetSubCategories returns a list of all subcategories of the given category ID.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* catid - The parent category ID to use. May be -1 to return all "top level" categories.
|
||||
* Returns:
|
||||
* List of subcategories of this category.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetSubCategories(catid int32) ([]*Category, error) {
|
||||
ok, err := isCatEnabled()
|
||||
func AmGetSubCategories(ctx context.Context, catid int32) ([]*Category, error) {
|
||||
ok, err := isCatEnabled(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return nil, errors.New("category feature not supported")
|
||||
}
|
||||
err = loadCategories()
|
||||
err = loadCategories(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -185,6 +189,7 @@ func AmGetSubCategories(catid int32) ([]*Category, error) {
|
||||
|
||||
/* AmSearchCategories searches for categories matching certain criteria.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* oper - The operation to perform on the category name:
|
||||
* SearchCatOperPrefix - The category name has the string "term" as a prefix.
|
||||
* SearchCatOperSubstring - The category name contains the string "term".
|
||||
@@ -197,8 +202,8 @@ func AmGetSubCategories(catid int32) ([]*Category, error) {
|
||||
* The total number of categories matching this query (could be greater than max)
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmSearchCategories(oper int, term string, offset int, max int, showAll bool, searchAll bool) ([]*Category, int, error) {
|
||||
ok, err := isCatEnabled()
|
||||
func AmSearchCategories(ctx context.Context, oper int, term string, offset int, max int, showAll bool, searchAll bool) ([]*Category, int, error) {
|
||||
ok, err := isCatEnabled(ctx)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
@@ -230,7 +235,7 @@ func AmSearchCategories(oper int, term string, offset int, max int, showAll bool
|
||||
queryString.WriteString(" AND hide_search = 0")
|
||||
}
|
||||
q := queryString.String()
|
||||
rs, err := amdb.Query("SELECT COUNT(*) FROM refcategory WHERE " + q)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT COUNT(*) FROM refcategory WHERE "+q)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
@@ -243,9 +248,9 @@ func AmSearchCategories(oper int, term string, offset int, max int, showAll bool
|
||||
return make([]*Category, 0), 0, nil
|
||||
}
|
||||
if offset > 0 {
|
||||
rs, err = amdb.Query("SELECT catid FROM refcategory WHERE "+q+" ORDER BY parent, name LIMIT ? OFFSET ?", max, offset)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT catid FROM refcategory WHERE "+q+" ORDER BY parent, name LIMIT ? OFFSET ?", max, offset)
|
||||
} else {
|
||||
rs, err = amdb.Query("SELECT catid FROM refcategory WHERE "+q+" ORDER BY parent, name LIMIT ?", max)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT catid FROM refcategory WHERE "+q+" ORDER BY parent, name LIMIT ?", max)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, total, err
|
||||
@@ -254,7 +259,7 @@ func AmSearchCategories(oper int, term string, offset int, max int, showAll bool
|
||||
for rs.Next() {
|
||||
var catid int32
|
||||
rs.Scan(&catid)
|
||||
c, err := AmGetCategory(catid)
|
||||
c, err := AmGetCategory(ctx, catid)
|
||||
if err == nil {
|
||||
rc = append(rc, c)
|
||||
}
|
||||
|
||||
+107
-90
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -151,27 +152,27 @@ func (c *Community) Public() bool {
|
||||
}
|
||||
|
||||
// ContactInfo returns the contact info structure for the community.
|
||||
func (c *Community) ContactInfo() (*ContactInfo, error) {
|
||||
func (c *Community) ContactInfo(ctx context.Context) (*ContactInfo, error) {
|
||||
if c.ContactId < 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return AmGetContactInfo(c.ContactId)
|
||||
return AmGetContactInfo(ctx, c.ContactId)
|
||||
}
|
||||
|
||||
// Host returns the reference to the host of the community.
|
||||
func (c *Community) Host() (*User, error) {
|
||||
func (c *Community) Host(ctx context.Context) (*User, error) {
|
||||
if c.HostUid == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return AmGetUser(*c.HostUid)
|
||||
return AmGetUser(ctx, *c.HostUid)
|
||||
}
|
||||
|
||||
// HostQ returns the reference to the community's host, quietly.
|
||||
func (c *Community) HostQ() *User {
|
||||
func (c *Community) HostQ(ctx context.Context) *User {
|
||||
if c.HostUid == nil {
|
||||
return nil
|
||||
}
|
||||
u, err := AmGetUser(*c.HostUid)
|
||||
u, err := AmGetUser(ctx, *c.HostUid)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -192,6 +193,7 @@ func (c *Community) LanguageTag() (*language.Tag, error) {
|
||||
|
||||
/* Membership returns the details of the specified user's membership in the community.
|
||||
* Parameters:
|
||||
* ctxt - Standard Go context value.
|
||||
* u - The user to check the membership of.
|
||||
* Returns:
|
||||
* true if the user is a member, false if not.
|
||||
@@ -199,7 +201,7 @@ func (c *Community) LanguageTag() (*language.Tag, error) {
|
||||
* User's access level in the community, or 0 if the user is not a member.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (c *Community) Membership(u *User) (bool, bool, uint16, error) {
|
||||
func (c *Community) Membership(ctx context.Context, u *User) (bool, bool, uint16, error) {
|
||||
key := fmt.Sprintf("%d:%d", c.Id, u.Uid)
|
||||
memberMutex.Lock()
|
||||
defer memberMutex.Unlock()
|
||||
@@ -212,7 +214,7 @@ func (c *Community) Membership(u *User) (bool, bool, uint16, error) {
|
||||
// "no join required" - they are effectively a member, but don't cache that
|
||||
return true, false, u.BaseLevel, nil
|
||||
}
|
||||
rs, err := amdb.Query("SELECT locked, granted_lvl FROM commmember WHERE commid = ? AND uid = ?", c.Id, u.Uid)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT locked, granted_lvl FROM commmember WHERE commid = ? AND uid = ?", c.Id, u.Uid)
|
||||
if err == nil {
|
||||
if rs.Next() {
|
||||
var locked bool
|
||||
@@ -227,13 +229,13 @@ func (c *Community) Membership(u *User) (bool, bool, uint16, error) {
|
||||
}
|
||||
|
||||
// MemberCount returns the number of members in the community.
|
||||
func (c *Community) MemberCount(hidden bool) (int, error) {
|
||||
func (c *Community) MemberCount(ctx context.Context, hidden bool) (int, error) {
|
||||
var rs *sql.Rows
|
||||
var err error
|
||||
if hidden {
|
||||
rs, err = amdb.Query("SELECT COUNT(*) FROM commmember WHERE commid = ?", c.Id)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT COUNT(*) FROM commmember WHERE commid = ?", c.Id)
|
||||
} else {
|
||||
rs, err = amdb.Query("SELECT COUNT(*) FROM commmember WHERE commid = ? AND hidden = 0", c.Id)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT COUNT(*) FROM commmember WHERE commid = ? AND hidden = 0", c.Id)
|
||||
}
|
||||
if err != nil {
|
||||
return -1, err
|
||||
@@ -248,6 +250,7 @@ func (c *Community) MemberCount(hidden bool) (int, error) {
|
||||
|
||||
/* ListMembers lists or searches for community members matching certain criteria.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* field - A value indicating which field to search:
|
||||
* ListMembersFieldNone - Do not search, just return all community members.
|
||||
* ListMembersFieldName - The user name.
|
||||
@@ -267,7 +270,7 @@ func (c *Community) MemberCount(hidden bool) (int, error) {
|
||||
* The total number of members matching this query (could be greater than max)
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (c *Community) ListMembers(field int, oper int, term string, offset int, max int, showHidden bool) ([]*User, int, error) {
|
||||
func (c *Community) ListMembers(ctx context.Context, field int, oper int, term string, offset int, max int, showHidden bool) ([]*User, int, error) {
|
||||
var query strings.Builder
|
||||
if field != ListMembersFieldNone && oper != ListMembersOperNone {
|
||||
query.WriteString(" AND ")
|
||||
@@ -304,7 +307,7 @@ func (c *Community) ListMembers(field int, oper int, term string, offset int, ma
|
||||
query.WriteString(" AND m.hidden = 0")
|
||||
}
|
||||
q := query.String()
|
||||
rs, err := amdb.Query(`SELECT COUNT(*) FROM commmember m, users u, contacts c WHERE m.commid = ? AND m.uid = u.uid
|
||||
rs, err := amdb.QueryContext(ctx, `SELECT COUNT(*) FROM commmember m, users u, contacts c WHERE m.commid = ? AND m.uid = u.uid
|
||||
AND u.contactid = c.contactid`+q, c.Id)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
@@ -315,10 +318,10 @@ func (c *Community) ListMembers(field int, oper int, term string, offset int, ma
|
||||
var total int
|
||||
rs.Scan(&total)
|
||||
if offset > 0 {
|
||||
rs, err = amdb.Query(`SELECT m.uid FROM commmember m, users u, contacts c WHERE m.commid = ? AND m.uid = u.uid
|
||||
rs, err = amdb.QueryContext(ctx, `SELECT m.uid FROM commmember m, users u, contacts c WHERE m.commid = ? AND m.uid = u.uid
|
||||
AND u.contactid = c.contactid`+q+" ORDER BY u.username LIMIT ? OFFSET ?", c.Id, max, offset)
|
||||
} else {
|
||||
rs, err = amdb.Query(`SELECT m.uid FROM commmember m, users u, contacts c WHERE m.commid = ? AND m.uid = u.uid
|
||||
rs, err = amdb.QueryContext(ctx, `SELECT m.uid FROM commmember m, users u, contacts c WHERE m.commid = ? AND m.uid = u.uid
|
||||
AND u.contactid = c.contactid`+q+" ORDER BY u.username LIMIT ?", c.Id, max)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -328,7 +331,7 @@ func (c *Community) ListMembers(field int, oper int, term string, offset int, ma
|
||||
for rs.Next() {
|
||||
var uid int32
|
||||
rs.Scan(&uid)
|
||||
u, err := AmGetUser(uid)
|
||||
u, err := AmGetUser(ctx, uid)
|
||||
if err == nil {
|
||||
rc = append(rc, u)
|
||||
}
|
||||
@@ -338,6 +341,7 @@ func (c *Community) ListMembers(field int, oper int, term string, offset int, ma
|
||||
|
||||
/* SetMembership sets a user's membership status within the community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* u - The user to change the membership status of.
|
||||
* level - Their membership level. If this is 0, they are removed from membership.
|
||||
* locked - Whether they can unjoin the community themselves. Ignored if removing them.
|
||||
@@ -346,7 +350,7 @@ func (c *Community) ListMembers(field int, oper int, term string, offset int, ma
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (c *Community) SetMembership(u *User, level uint16, locked bool, personUID int32, ipaddr string) error {
|
||||
func (c *Community) SetMembership(ctx context.Context, u *User, level uint16, locked bool, personUID int32, ipaddr string) error {
|
||||
success := false
|
||||
tx := amdb.MustBegin()
|
||||
defer func() {
|
||||
@@ -355,20 +359,20 @@ func (c *Community) SetMembership(u *User, level uint16, locked bool, personUID
|
||||
}
|
||||
}()
|
||||
if level == 0 {
|
||||
res, err := tx.Exec("DELETE FROM commmember WHERE commid = ? AND uid = ?", c.Id, u.Uid)
|
||||
res, err := tx.ExecContext(ctx, "DELETE FROM commmember WHERE commid = ? AND uid = ?", c.Id, u.Uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stuffMembership(c.Id, u.Uid, false, false, 0)
|
||||
ra, err := res.RowsAffected()
|
||||
if err == nil && ra > 0 {
|
||||
err = AmOnUserLeaveCommunityServices(tx, c, u)
|
||||
err = AmOnUserLeaveCommunityServices(ctx, tx, c, u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rs, err := tx.Query("SELECT granted_lvl, locked FROM commmember WHERE commid = ? AND uid = ?", c.Id, u.Uid)
|
||||
rs, err := tx.QueryContext(ctx, "SELECT granted_lvl, locked FROM commmember WHERE commid = ? AND uid = ?", c.Id, u.Uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -377,7 +381,7 @@ func (c *Community) SetMembership(u *User, level uint16, locked bool, personUID
|
||||
var lockStatus bool
|
||||
rs.Scan(&oldLevel, &lockStatus)
|
||||
if level != oldLevel || lockStatus != locked {
|
||||
_, err := tx.Exec("UPDATE commmember SET granted_lvl = ?, locked = ? WHERE commid = ? AND uid = ?",
|
||||
_, err := tx.ExecContext(ctx, "UPDATE commmember SET granted_lvl = ?, locked = ? WHERE commid = ? AND uid = ?",
|
||||
level, locked, c.Id, u.Uid)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -385,19 +389,19 @@ func (c *Community) SetMembership(u *User, level uint16, locked bool, personUID
|
||||
stuffMembership(c.Id, u.Uid, true, locked, level)
|
||||
}
|
||||
} else {
|
||||
_, err := tx.Exec("INSERT INTO commmember (commid, uid, granted_lvl, locked) VALUES (?, ?, ?, ?)",
|
||||
_, err := tx.ExecContext(ctx, "INSERT INTO commmember (commid, uid, granted_lvl, locked) VALUES (?, ?, ?, ?)",
|
||||
c.Id, u.Uid, level, locked)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stuffMembership(c.Id, u.Uid, true, locked, level)
|
||||
err = AmOnUserJoinCommunityServices(tx, c, u)
|
||||
err = AmOnUserJoinCommunityServices(ctx, tx, c, u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
err := c.TouchUpdateTx(tx)
|
||||
err := c.TouchUpdateTx(ctx, tx)
|
||||
if err == nil {
|
||||
ar := AmNewAudit(AuditCommunitySetMembership, personUID, ipaddr, fmt.Sprintf("cid=%d", c.Id),
|
||||
fmt.Sprintf("uid=%d", u.Uid), fmt.Sprintf("level=%d", level))
|
||||
@@ -450,11 +454,11 @@ func (c *Community) PermissionLevel(perm string) uint16 {
|
||||
}
|
||||
|
||||
// GetFlags retrieves the flags from the properties.
|
||||
func (c *Community) Flags() (*util.OptionSet, error) {
|
||||
func (c *Community) Flags(ctx context.Context) (*util.OptionSet, error) {
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
if c.flags == nil {
|
||||
s, err := AmGetCommunityProperty(c.Id, CommunityPropFlags)
|
||||
s, err := AmGetCommunityProperty(ctx, c.Id, CommunityPropFlags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -468,11 +472,11 @@ func (c *Community) Flags() (*util.OptionSet, error) {
|
||||
}
|
||||
|
||||
// SaveFlags writes the flags to the database and stores them.
|
||||
func (c *Community) SaveFlags(f *util.OptionSet) error {
|
||||
func (c *Community) SaveFlags(ctx context.Context, f *util.OptionSet) error {
|
||||
s := f.AsString()
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
err := AmSetCommunityProperty(c.Id, CommunityPropFlags, &s)
|
||||
err := AmSetCommunityProperty(ctx, c.Id, CommunityPropFlags, &s)
|
||||
if err == nil {
|
||||
c.flags = f
|
||||
}
|
||||
@@ -480,12 +484,12 @@ func (c *Community) SaveFlags(f *util.OptionSet) error {
|
||||
}
|
||||
|
||||
// SetProfileData sets all the "settable" profile data
|
||||
func (c *Community) SetProfileData(name string, alias string, synopsis *string, rules *string, language *string,
|
||||
func (c *Community) SetProfileData(ctx context.Context, name string, alias string, synopsis *string, rules *string, language *string,
|
||||
joinkey *string, membersonly bool, hideDirectory bool, hideSearch bool, read_lvl uint16, write_lvl uint16,
|
||||
create_lvl uint16, delete_lvl uint16, join_lvl uint16) error {
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
_, err := amdb.Exec(`UPDATE communities SET commname = ?, alias = ?, synopsis = ?, rules = ?, language = ?,
|
||||
_, err := amdb.ExecContext(ctx, `UPDATE communities SET commname = ?, alias = ?, synopsis = ?, rules = ?, language = ?,
|
||||
joinkey = ?, membersonly = ?, hide_dir = ?, hide_search = ?, read_lvl = ?, write_lvl = ?, create_lvl = ?,
|
||||
delete_lvl = ?, join_lvl = ?, lastupdate = NOW() WHERE commid = ?`,
|
||||
name, alias, synopsis, rules, language, joinkey, membersonly, hideDirectory, hideSearch, read_lvl, write_lvl,
|
||||
@@ -505,7 +509,7 @@ func (c *Community) SetProfileData(name string, alias string, synopsis *string,
|
||||
c.CreateLevel = create_lvl
|
||||
c.DeleteLevel = delete_lvl
|
||||
c.JoinLevel = join_lvl
|
||||
rs, err2 := amdb.Query("SELECT lastupdate FROM communities WHERE commid = ?", c.Id)
|
||||
rs, err2 := amdb.QueryContext(ctx, "SELECT lastupdate FROM communities WHERE commid = ?", c.Id)
|
||||
if err2 != nil {
|
||||
rs.Next()
|
||||
rs.Scan(&c.LastUpdate)
|
||||
@@ -515,10 +519,10 @@ func (c *Community) SetProfileData(name string, alias string, synopsis *string,
|
||||
}
|
||||
|
||||
// SetContactID sets the contact ID for the community.
|
||||
func (c *Community) SetContactID(cid int32) error {
|
||||
func (c *Community) SetContactID(ctx context.Context, cid int32) error {
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
if _, err := amdb.Exec("UPDATE communities SET contactid = ? WHERE commid = ?", cid, c.Id); err != nil {
|
||||
if _, err := amdb.ExecContext(ctx, "UPDATE communities SET contactid = ? WHERE commid = ?", cid, c.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
c.ContactId = cid
|
||||
@@ -526,12 +530,12 @@ func (c *Community) SetContactID(cid int32) error {
|
||||
}
|
||||
|
||||
// Touch updates the last access time of the community.
|
||||
func (c *Community) Touch() error {
|
||||
func (c *Community) Touch(ctx context.Context) error {
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
_, err := amdb.Exec("UPDATE communities SET lastaccess = NOW() WHERE commid = ?", c.Id)
|
||||
_, err := amdb.ExecContext(ctx, "UPDATE communities SET lastaccess = NOW() WHERE commid = ?", c.Id)
|
||||
if err == nil {
|
||||
rs, err := amdb.Query("SELECT lastaccess FROM communities WHERE commid = ?", c.Id)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT lastaccess FROM communities WHERE commid = ?", c.Id)
|
||||
if err == nil {
|
||||
rs.Next()
|
||||
var na time.Time
|
||||
@@ -543,12 +547,12 @@ func (c *Community) Touch() error {
|
||||
}
|
||||
|
||||
// TouchUpdateTx updates the last access and last update times of the community.
|
||||
func (c *Community) TouchUpdateTx(tx *sqlx.Tx) error {
|
||||
func (c *Community) TouchUpdateTx(ctx context.Context, tx *sqlx.Tx) error {
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
_, err := tx.Exec("UPDATE communities SET lastaccess = NOW(), lastupdate = NOW() WHERE commid = ?", c.Id)
|
||||
_, err := tx.ExecContext(ctx, "UPDATE communities SET lastaccess = NOW(), lastupdate = NOW() WHERE commid = ?", c.Id)
|
||||
if err == nil {
|
||||
rs, err := tx.Query("SELECT lastaccess, lastupdate FROM communities WHERE commid = ?", c.Id)
|
||||
rs, err := tx.QueryContext(ctx, "SELECT lastaccess, lastupdate FROM communities WHERE commid = ?", c.Id)
|
||||
if err != nil {
|
||||
rs.Next()
|
||||
var na, nu time.Time
|
||||
@@ -561,9 +565,9 @@ func (c *Community) TouchUpdateTx(tx *sqlx.Tx) error {
|
||||
}
|
||||
|
||||
// TouchUpdateTx updates the last access and last update times of the community.
|
||||
func (c *Community) TouchUpdate() error {
|
||||
func (c *Community) TouchUpdate(ctx context.Context) error {
|
||||
tx := amdb.MustBegin()
|
||||
err := c.TouchUpdateTx(tx)
|
||||
err := c.TouchUpdateTx(ctx, tx)
|
||||
if err != nil {
|
||||
err = tx.Commit()
|
||||
}
|
||||
@@ -575,18 +579,19 @@ func (c *Community) TouchUpdate() error {
|
||||
|
||||
/* AmGetCommunity returns a reference to the specified community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* id - The ID of the community.
|
||||
* Returns:
|
||||
* Pointer to Community containing community data, or nil
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmGetCommunity(id int32) (*Community, error) {
|
||||
func AmGetCommunity(ctx context.Context, id int32) (*Community, error) {
|
||||
getCommunityMutex.Lock()
|
||||
defer getCommunityMutex.Unlock()
|
||||
rc, ok := communityCache.Get(id)
|
||||
if !ok {
|
||||
var dbdata []Community
|
||||
err := amdb.Select(&dbdata, "SELECT * from communities WHERE commid = ?", id)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * from communities WHERE commid = ?", id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -603,19 +608,20 @@ func AmGetCommunity(id int32) (*Community, error) {
|
||||
|
||||
/* AmGetCommunityTx returns a reference to the specified community, in a transaction.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* tx - The transaction to use.
|
||||
* id - The ID of the community.
|
||||
* Returns:
|
||||
* Pointer to Community containing community data, or nil
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmGetCommunityTx(tx *sqlx.Tx, id int32) (*Community, error) {
|
||||
func AmGetCommunityTx(ctx context.Context, tx *sqlx.Tx, id int32) (*Community, error) {
|
||||
getCommunityMutex.Lock()
|
||||
defer getCommunityMutex.Unlock()
|
||||
rc, ok := communityCache.Get(id)
|
||||
if !ok {
|
||||
var dbdata []Community
|
||||
err := tx.Select(&dbdata, "SELECT * from communities WHERE commid = ?", id)
|
||||
err := tx.SelectContext(ctx, &dbdata, "SELECT * from communities WHERE commid = ?", id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -632,18 +638,19 @@ func AmGetCommunityTx(tx *sqlx.Tx, id int32) (*Community, error) {
|
||||
|
||||
/* AmGetCommunityByAlias returns a reference to the specified community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* alias - The alias for the community.
|
||||
* Returns:
|
||||
* Pointer to Community containing community data, or nil
|
||||
* Standard Go error status (nil if community not found)
|
||||
*/
|
||||
func AmGetCommunityByAlias(alias string) (*Community, error) {
|
||||
rs, err := amdb.Query("SELECT commid FROM communities WHERE alias = ?", alias)
|
||||
func AmGetCommunityByAlias(ctx context.Context, alias string) (*Community, error) {
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT commid FROM communities WHERE alias = ?", alias)
|
||||
if err == nil {
|
||||
if rs.Next() {
|
||||
var cid int32
|
||||
rs.Scan(&cid)
|
||||
return AmGetCommunity(cid)
|
||||
return AmGetCommunity(ctx, cid)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -653,19 +660,20 @@ func AmGetCommunityByAlias(alias string) (*Community, error) {
|
||||
|
||||
/* AmGetCommunityByAliasTx returns a reference to the specified community, within a transaction.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* tx - The transaction to use.
|
||||
* alias - The alias for the community.
|
||||
* Returns:
|
||||
* Pointer to Community containing community data, or nil
|
||||
* Standard Go error status (nil if community not found)
|
||||
*/
|
||||
func AmGetCommunityByAliasTx(tx *sqlx.Tx, alias string) (*Community, error) {
|
||||
rs, err := tx.Query("SELECT commid FROM communities WHERE alias = ?", alias)
|
||||
func AmGetCommunityByAliasTx(ctx context.Context, tx *sqlx.Tx, alias string) (*Community, error) {
|
||||
rs, err := tx.QueryContext(ctx, "SELECT commid FROM communities WHERE alias = ?", alias)
|
||||
if err == nil {
|
||||
if rs.Next() {
|
||||
var cid int32
|
||||
rs.Scan(&cid)
|
||||
return AmGetCommunityTx(tx, cid)
|
||||
return AmGetCommunityTx(ctx, tx, cid)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -677,21 +685,22 @@ func AmGetCommunityByAliasTx(tx *sqlx.Tx, alias string) (*Community, error) {
|
||||
* If the parameter is numeric, it's interpreted as a community ID. Otherwise, it's interpreted
|
||||
* as a community alias.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* id - The ID of the community.
|
||||
* Returns:
|
||||
* Pointer to Community containing community data, or nil
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmGetCommunityFromParam(param string) (*Community, error) {
|
||||
func AmGetCommunityFromParam(ctx context.Context, param string) (*Community, error) {
|
||||
if util.IsNumeric(param) {
|
||||
v, _ := strconv.Atoi(param)
|
||||
c, err := AmGetCommunity(int32(v))
|
||||
c, err := AmGetCommunity(ctx, int32(v))
|
||||
if err == nil {
|
||||
return c, nil
|
||||
}
|
||||
// else fall through to trying as alias
|
||||
}
|
||||
rc, err := AmGetCommunityByAlias(param)
|
||||
rc, err := AmGetCommunityByAlias(ctx, param)
|
||||
if err == nil {
|
||||
if rc == nil {
|
||||
return nil, fmt.Errorf("community with alias \"%s\" not found", param)
|
||||
@@ -702,18 +711,19 @@ func AmGetCommunityFromParam(param string) (*Community, error) {
|
||||
|
||||
/* AmGetCommunitiesForUser returns a list of communities the user is a member of.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* uid - The ID of the user.
|
||||
* Returns:
|
||||
* Array of pointers to communities for the user
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmGetCommunitiesForUser(uid int32) ([]*Community, error) {
|
||||
func AmGetCommunitiesForUser(ctx context.Context, uid int32) ([]*Community, error) {
|
||||
var rc []*Community = make([]*Community, 0)
|
||||
var ids []int32 = make([]int32, 0)
|
||||
err := amdb.Select(&ids, "SELECT commid FROM commmember WHERE uid = ?", uid)
|
||||
err := amdb.SelectContext(ctx, &ids, "SELECT commid FROM commmember WHERE uid = ?", uid)
|
||||
if err == nil {
|
||||
for _, id := range ids {
|
||||
c, err := AmGetCommunity(id)
|
||||
c, err := AmGetCommunity(ctx, id)
|
||||
if err == nil {
|
||||
rc = append(rc, c)
|
||||
} else {
|
||||
@@ -727,15 +737,16 @@ func AmGetCommunitiesForUser(uid int32) ([]*Community, error) {
|
||||
/* AmGetCommunityAccessLevel returns the access level of the specified user with respect to the community.
|
||||
* This may reflect the user's admin status as well as their status within the community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* uid - The UID of the user.
|
||||
* commid - The ID of the community.
|
||||
* Returns:
|
||||
* Access level within the community, or 0 if the user is not a member.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetCommunityAccessLevel(uid int32, commid int32) (uint16, error) {
|
||||
func AmGetCommunityAccessLevel(ctx context.Context, uid int32, commid int32) (uint16, error) {
|
||||
var rc uint16 = 0
|
||||
rows, err := amdb.Queryx(`SELECT GREATEST(m.granted_lvl, u.base_lvl) AS level FROM users u, commmember m
|
||||
rows, err := amdb.QueryxContext(ctx, `SELECT GREATEST(m.granted_lvl, u.base_lvl) AS level FROM users u, commmember m
|
||||
WHERE u.uid = m.uid AND m.uid = ? AND m.commid = ?`, uid, commid)
|
||||
if err == nil {
|
||||
defer rows.Close()
|
||||
@@ -748,21 +759,22 @@ func AmGetCommunityAccessLevel(uid int32, commid int32) (uint16, error) {
|
||||
|
||||
/* AmAutoJoinCommunities joins the specified user to any communities they're not yet a part of.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* tx - The current transaction to be used for database access.
|
||||
* user - The user to be auto-joined to communities.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmAutoJoinCommunities(tx *sqlx.Tx, user *User) error {
|
||||
func AmAutoJoinCommunities(ctx context.Context, tx *sqlx.Tx, user *User) error {
|
||||
// get list of current communities
|
||||
var current []int32 = make([]int32, 0)
|
||||
err := tx.Select(¤t, "SELECT commid FROM commmember WHERE uid = ?", user.Uid)
|
||||
err := tx.SelectContext(ctx, ¤t, "SELECT commid FROM commmember WHERE uid = ?", user.Uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// look for candidate communities
|
||||
rows, err := tx.Queryx(`SELECT m.commid, m.locked FROM users u, communities c, commmember m
|
||||
rows, err := tx.QueryxContext(ctx, `SELECT m.commid, m.locked FROM users u, communities c, commmember m
|
||||
WHERE m.uid = u.uid AND m.commid = c.commid AND u.is_anon = 1 AND c.join_lvl <= ?`, user.BaseLevel)
|
||||
if err == nil {
|
||||
defer rows.Close()
|
||||
@@ -772,7 +784,7 @@ func AmAutoJoinCommunities(tx *sqlx.Tx, user *User) error {
|
||||
var lock bool
|
||||
rows.Scan(&cid, &lock)
|
||||
if !slices.Contains(current, cid) {
|
||||
_, err = tx.Exec("INSERT INTO commmember (commid, uid, granted_lvl, locked) VALUES (?, ?, ?, ?)",
|
||||
_, err = tx.ExecContext(ctx, "INSERT INTO commmember (commid, uid, granted_lvl, locked) VALUES (?, ?, ?, ?)",
|
||||
cid, user.Uid, grantLevel, lock)
|
||||
if err != nil {
|
||||
break
|
||||
@@ -785,7 +797,7 @@ func AmAutoJoinCommunities(tx *sqlx.Tx, user *User) error {
|
||||
}
|
||||
|
||||
// internalGetProp is a helper used by the property functions.
|
||||
func internalGetCommProp(cid int32, ndx int32) (*CommunityProperties, error) {
|
||||
func internalGetCommProp(ctx context.Context, cid int32, ndx int32) (*CommunityProperties, error) {
|
||||
var err error = nil
|
||||
key := fmt.Sprintf("%d:%d", cid, ndx)
|
||||
getCommunityPropMutex.Lock()
|
||||
@@ -793,7 +805,7 @@ func internalGetCommProp(cid int32, ndx int32) (*CommunityProperties, error) {
|
||||
rc, ok := communityPropCache.Get(key)
|
||||
if !ok {
|
||||
var dbdata []CommunityProperties
|
||||
err = amdb.Select(&dbdata, "SELECT * from propcomm WHERE cid = ? AND ndx = ?", cid, ndx)
|
||||
err = amdb.SelectContext(ctx, &dbdata, "SELECT * from propcomm WHERE cid = ? AND ndx = ?", cid, ndx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -811,14 +823,15 @@ func internalGetCommProp(cid int32, ndx int32) (*CommunityProperties, error) {
|
||||
|
||||
/* AmGetCommunityProperty retrieves the value of a user property.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* cid - The ID of the community to get the property for.
|
||||
* ndx - The index of the property to retrieve.
|
||||
* Returns:
|
||||
* Value of the property string.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetCommunityProperty(cid int32, ndx int32) (*string, error) {
|
||||
p, err := internalGetCommProp(cid, ndx)
|
||||
func AmGetCommunityProperty(ctx context.Context, cid int32, ndx int32) (*string, error) {
|
||||
p, err := internalGetCommProp(ctx, cid, ndx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if p == nil {
|
||||
@@ -829,27 +842,28 @@ func AmGetCommunityProperty(cid int32, ndx int32) (*string, error) {
|
||||
|
||||
/* AmSetCommunityProperty sets the value of a community property.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* cid - The ID of the community to set the property for.
|
||||
* ndx - The index of the property to set.
|
||||
* val - The new value of the property.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmSetCommunityProperty(cid int32, ndx int32, val *string) error {
|
||||
p, err := internalGetCommProp(cid, ndx)
|
||||
func AmSetCommunityProperty(ctx context.Context, cid int32, ndx int32, val *string) error {
|
||||
p, err := internalGetCommProp(ctx, cid, ndx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
getCommunityPropMutex.Lock()
|
||||
defer getCommunityPropMutex.Unlock()
|
||||
if p != nil {
|
||||
_, err = amdb.Exec("UPDATE propcomm SET data = ? WHERE cid = ? AND ndx = ?", val, cid, ndx)
|
||||
_, err = amdb.ExecContext(ctx, "UPDATE propcomm SET data = ? WHERE cid = ? AND ndx = ?", val, cid, ndx)
|
||||
if err == nil {
|
||||
p.Data = val
|
||||
}
|
||||
} else {
|
||||
prop := CommunityProperties{Cid: cid, Index: ndx, Data: val}
|
||||
_, err := amdb.NamedExec("INSERT INTO propcomm (cid, ndx, data) VALUES(:cid, :ndx, :data)", prop)
|
||||
_, err := amdb.NamedExecContext(ctx, "INSERT INTO propcomm (cid, ndx, data) VALUES(:cid, :ndx, :data)", prop)
|
||||
if err == nil {
|
||||
communityPropCache.Add(fmt.Sprintf("%d:%d", cid, ndx), prop)
|
||||
}
|
||||
@@ -859,6 +873,7 @@ func AmSetCommunityProperty(cid int32, ndx int32, val *string) error {
|
||||
|
||||
/* AmCreateCommunity creates a new community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* name - The name for the new community.
|
||||
* alias - The alias for the new community. Must be unique.
|
||||
* hostUid - The UID of the creator and new host of the community.
|
||||
@@ -873,7 +888,7 @@ func AmSetCommunityProperty(cid int32, ndx int32, val *string) error {
|
||||
* Pointer to new Community record, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmCreateCommunity(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) {
|
||||
var ar *AuditRecord = nil
|
||||
defer func() {
|
||||
@@ -888,7 +903,7 @@ func AmCreateCommunity(name string, alias string, hostUid int32, language *strin
|
||||
}()
|
||||
|
||||
// validate alias does not already exist
|
||||
rs, err := tx.Query("SELECT commid FROM communities WHERE alias = ?", alias)
|
||||
rs, err := tx.QueryContext(ctx, "SELECT commid FROM communities WHERE alias = ?", alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -897,7 +912,7 @@ func AmCreateCommunity(name string, alias string, hostUid int32, language *strin
|
||||
}
|
||||
|
||||
// establish the community record
|
||||
_, err = tx.Exec(`INSERT INTO communities (createdate, lastaccess, lastupdate, read_lvl, write_lvl,
|
||||
_, err = tx.ExecContext(ctx, `INSERT INTO communities (createdate, lastaccess, lastupdate, read_lvl, write_lvl,
|
||||
create_lvl, delete_lvl, join_lvl, host_uid, hide_dir, hide_search, commname, language,
|
||||
synopsis, rules, joinkey, alias) VALUES (NOW(), NOW(), NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
AmRoleList("Community.Read").Default().Level(), AmRoleList("Community.Write").Default().Level(),
|
||||
@@ -909,7 +924,7 @@ func AmCreateCommunity(name string, alias string, hostUid int32, language *strin
|
||||
}
|
||||
|
||||
// Read back the community, which also puts it in the cache.
|
||||
comm, err := AmGetCommunityByAliasTx(tx, alias)
|
||||
comm, err := AmGetCommunityByAliasTx(ctx, tx, alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if comm == nil {
|
||||
@@ -918,7 +933,7 @@ func AmCreateCommunity(name string, alias string, hostUid int32, language *strin
|
||||
|
||||
// Ensure the new host has host privileges in the community. The host's membership is "locked" so they
|
||||
// can't unjoin and leave the community hostless.
|
||||
_, err = tx.Exec("INSERT INTO commmember (commid, uid, granted_lvl, locked) VALUES (?, ?, ?, 1)", comm.Id, hostUid,
|
||||
_, err = tx.ExecContext(ctx, "INSERT INTO commmember (commid, uid, granted_lvl, locked) VALUES (?, ?, ?, 1)", comm.Id, hostUid,
|
||||
AmDefaultRole("Community.Creator").Level())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -926,7 +941,7 @@ func AmCreateCommunity(name string, alias string, hostUid int32, language *strin
|
||||
stuffMembership(comm.Id, hostUid, true, true, AmDefaultRole("Community.Creator").Level())
|
||||
|
||||
// Establish the community services.
|
||||
err = AmEstablishCommunityServices(tx, comm)
|
||||
err = AmEstablishCommunityServices(ctx, tx, comm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -945,6 +960,7 @@ func AmCreateCommunity(name string, alias string, hostUid int32, language *strin
|
||||
|
||||
/* AmGetCommunitiesForCategory returns a list of communities for the specified category.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* catid - Category ID to search for.
|
||||
* offset - Number of communities to skip at beginning of list.
|
||||
* max - Maximum number of communities to return.
|
||||
@@ -954,13 +970,13 @@ func AmCreateCommunity(name string, alias string, hostUid int32, language *strin
|
||||
* The total number of communities matching this query (could be greater than max)
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetCommunitiesForCategory(catid int32, offset int, max int, showAll bool) ([]*Community, int, error) {
|
||||
func AmGetCommunitiesForCategory(ctx context.Context, catid int32, offset int, max int, showAll bool) ([]*Community, int, error) {
|
||||
var rs *sql.Rows
|
||||
var err error
|
||||
if showAll {
|
||||
rs, err = amdb.Query("SELECT COUNT(*) FROM communities WHERE catid = ?", catid)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT COUNT(*) FROM communities WHERE catid = ?", catid)
|
||||
} else {
|
||||
rs, err = amdb.Query("SELECT COUNT(*) FROM communities WHERE catid = ? AND hide_dir = 0", catid)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT COUNT(*) FROM communities WHERE catid = ? AND hide_dir = 0", catid)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
@@ -975,17 +991,17 @@ func AmGetCommunitiesForCategory(catid int32, offset int, max int, showAll bool)
|
||||
}
|
||||
if showAll {
|
||||
if offset > 0 {
|
||||
rs, err = amdb.Query("SELECT commid FROM communities WHERE catid = ? ORDER BY commname LIMIT ? OFFSET ?",
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT commid FROM communities WHERE catid = ? ORDER BY commname LIMIT ? OFFSET ?",
|
||||
catid, max, offset)
|
||||
} else {
|
||||
rs, err = amdb.Query("SELECT commid FROM communities WHERE catid = ? ORDER BY commname LIMIT ?", catid, max)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT commid FROM communities WHERE catid = ? ORDER BY commname LIMIT ?", catid, max)
|
||||
}
|
||||
} else {
|
||||
if offset > 0 {
|
||||
rs, err = amdb.Query("SELECT commid FROM communities WHERE catid = ? AND hide_dir = 0 ORDER BY commname LIMIT ? OFFSET ?",
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT commid FROM communities WHERE catid = ? AND hide_dir = 0 ORDER BY commname LIMIT ? OFFSET ?",
|
||||
catid, max, offset)
|
||||
} else {
|
||||
rs, err = amdb.Query("SELECT commid FROM communities WHERE catid = ? AND hide_dir = 0 ORDER BY commname LIMIT ?", catid, max)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT commid FROM communities WHERE catid = ? AND hide_dir = 0 ORDER BY commname LIMIT ?", catid, max)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@@ -995,7 +1011,7 @@ func AmGetCommunitiesForCategory(catid int32, offset int, max int, showAll bool)
|
||||
for rs.Next() {
|
||||
var commid int32
|
||||
rs.Scan(&commid)
|
||||
c, err := AmGetCommunity(commid)
|
||||
c, err := AmGetCommunity(ctx, commid)
|
||||
if err == nil {
|
||||
rc = append(rc, c)
|
||||
}
|
||||
@@ -1005,6 +1021,7 @@ func AmGetCommunitiesForCategory(catid int32, offset int, max int, showAll bool)
|
||||
|
||||
/* AmSearchCommunities searches for communities matching certain criteria.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* field - A value indicating which field to search:
|
||||
* SearchCommFieldName - The community name.
|
||||
* SearchCommFieldSynopsis - The communty synopsis.
|
||||
@@ -1021,7 +1038,7 @@ func AmGetCommunitiesForCategory(catid int32, offset int, max int, showAll bool)
|
||||
* The total number of communities matching this query (could be greater than max)
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmSearchCommunities(field int, oper int, term string, offset int, max int, showAll bool) ([]*Community, int, error) {
|
||||
func AmSearchCommunities(ctx context.Context, field int, oper int, term string, offset int, max int, showAll bool) ([]*Community, int, error) {
|
||||
var queryPortion strings.Builder
|
||||
queryPortion.WriteString("WHERE ")
|
||||
switch field {
|
||||
@@ -1052,7 +1069,7 @@ func AmSearchCommunities(field int, oper int, term string, offset int, max int,
|
||||
queryPortion.WriteString(" AND hide_search = 0")
|
||||
}
|
||||
q := queryPortion.String()
|
||||
rs, err := amdb.Query("SELECT COUNT(*) FROM communities " + q)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT COUNT(*) FROM communities "+q)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
@@ -1065,9 +1082,9 @@ func AmSearchCommunities(field int, oper int, term string, offset int, max int,
|
||||
return make([]*Community, 0), 0, nil // short-circuit return
|
||||
}
|
||||
if offset > 0 {
|
||||
rs, err = amdb.Query("SELECT commid FROM communities "+q+" ORDER BY commname LIMIT ? OFFSET ?", max, offset)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT commid FROM communities "+q+" ORDER BY commname LIMIT ? OFFSET ?", max, offset)
|
||||
} else {
|
||||
rs, err = amdb.Query("SELECT commid FROM communities "+q+" ORDER BY commname LIMIT ?", max)
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT commid FROM communities "+q+" ORDER BY commname LIMIT ?", max)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, total, err
|
||||
@@ -1076,7 +1093,7 @@ func AmSearchCommunities(field int, oper int, term string, offset int, max int,
|
||||
for rs.Next() {
|
||||
var commid int32
|
||||
rs.Scan(&commid)
|
||||
c, err := AmGetCommunity(commid)
|
||||
c, err := AmGetCommunity(ctx, commid)
|
||||
if err == nil {
|
||||
rc = append(rc, c)
|
||||
}
|
||||
|
||||
+40
-35
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
@@ -66,8 +67,8 @@ func init() {
|
||||
}
|
||||
|
||||
// Aliases returns the list of aliases for this conference.
|
||||
func (c *Conference) Aliases() ([]string, error) {
|
||||
rs, err := amdb.Query("SELECT alias FROM confalias WHERE confid = ? ORDER BY alias", c.ConfId)
|
||||
func (c *Conference) Aliases(ctx context.Context) ([]string, error) {
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT alias FROM confalias WHERE confid = ? ORDER BY alias", c.ConfId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -81,14 +82,14 @@ func (c *Conference) Aliases() ([]string, error) {
|
||||
}
|
||||
|
||||
// AliasesQ returns the list of aliases for this conference, quietly.
|
||||
func (c *Conference) AliasesQ() []string {
|
||||
rc, _ := c.Aliases()
|
||||
func (c *Conference) AliasesQ(ctx context.Context) []string {
|
||||
rc, _ := c.Aliases(ctx)
|
||||
return rc
|
||||
}
|
||||
|
||||
// Hosts returns the list of users that host this conference.
|
||||
func (c *Conference) Hosts() ([]*User, error) {
|
||||
rs, err := amdb.Query("SELECT uid FROM confmember WHERE confid = ? AND granted_lvl = ?",
|
||||
func (c *Conference) Hosts(ctx context.Context) ([]*User, error) {
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT uid FROM confmember WHERE confid = ? AND granted_lvl = ?",
|
||||
c.ConfId, AmRole("Conference.Host").Level())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -97,7 +98,7 @@ func (c *Conference) Hosts() ([]*User, error) {
|
||||
for rs.Next() {
|
||||
var uid int32
|
||||
rs.Scan(&uid)
|
||||
u, err := AmGetUser(uid)
|
||||
u, err := AmGetUser(ctx, uid)
|
||||
if err == nil {
|
||||
rc = append(rc, u)
|
||||
}
|
||||
@@ -106,14 +107,14 @@ func (c *Conference) Hosts() ([]*User, error) {
|
||||
}
|
||||
|
||||
// Hosts returns the list of users that host this conference, quietly.
|
||||
func (c *Conference) HostsQ() []*User {
|
||||
rc, _ := c.Hosts()
|
||||
func (c *Conference) HostsQ(ctx context.Context) []*User {
|
||||
rc, _ := c.Hosts(ctx)
|
||||
return rc
|
||||
}
|
||||
|
||||
// Membership returns a membership flag and granted level for the user in this conference.
|
||||
func (c *Conference) Membership(u *User) (bool, uint16, error) {
|
||||
rs, err := amdb.Query("SELECT granted_lvl FROM confmember WHERE confid = ? AND uid = ?", c.ConfId, u.Uid)
|
||||
func (c *Conference) Membership(ctx context.Context, u *User) (bool, uint16, error) {
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT granted_lvl FROM confmember WHERE confid = ? AND uid = ?", c.ConfId, u.Uid)
|
||||
if err != nil {
|
||||
return false, 0, err
|
||||
}
|
||||
@@ -155,9 +156,9 @@ func (c *Conference) TestPermission(perm string, level uint16) bool {
|
||||
}
|
||||
|
||||
// Settings returns the settings for a user.
|
||||
func (c *Conference) Settings(u *User) (*ConferenceSettings, error) {
|
||||
func (c *Conference) Settings(ctx context.Context, u *User) (*ConferenceSettings, error) {
|
||||
var dbdata []ConferenceSettings
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM confsettings WHERE confid = ? AND uid = ?", c.ConfId, u.Uid)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * FROM confsettings WHERE confid = ? AND uid = ?", c.ConfId, u.Uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -171,24 +172,24 @@ func (c *Conference) Settings(u *User) (*ConferenceSettings, error) {
|
||||
}
|
||||
|
||||
// TouchRead updates the "last posted" date/time in the conference for the user.
|
||||
func (c *Conference) TouchRead(tx *sqlx.Tx, u *User) (*ConferenceSettings, error) {
|
||||
cs, err := c.Settings(u)
|
||||
func (c *Conference) TouchRead(ctx context.Context, tx *sqlx.Tx, u *User) (*ConferenceSettings, error) {
|
||||
cs, err := c.Settings(ctx, u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !u.IsAnon { // anon user can't update squat
|
||||
if cs == nil {
|
||||
ci, cerr := u.ContactInfo()
|
||||
ci, cerr := u.ContactInfo(ctx)
|
||||
if cerr != nil {
|
||||
return nil, cerr
|
||||
}
|
||||
_, err = tx.Exec("INSERT INTO confsettings (confid, uid, default_pseud, last_read) VALUES (?, ?, ?, NOW())",
|
||||
_, err = tx.ExecContext(ctx, "INSERT INTO confsettings (confid, uid, default_pseud, last_read) VALUES (?, ?, ?, NOW())",
|
||||
c.ConfId, u.Uid, ci.FullName(false))
|
||||
} else {
|
||||
_, err = tx.Exec("UPDATE confsettings SET last_read = NOW() WHERE confid = ? AND uid = ?", c.ConfId, u.Uid)
|
||||
_, err = tx.ExecContext(ctx, "UPDATE confsettings SET last_read = NOW() WHERE confid = ? AND uid = ?", c.ConfId, u.Uid)
|
||||
}
|
||||
if err == nil {
|
||||
cs, err = c.Settings(u) // reread to get updated or inserted values
|
||||
cs, err = c.Settings(ctx, u) // reread to get updated or inserted values
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -198,14 +199,14 @@ func (c *Conference) TouchRead(tx *sqlx.Tx, u *User) (*ConferenceSettings, error
|
||||
}
|
||||
|
||||
// TouchPost updates the "last posted" date/time in the conference for the user.
|
||||
func (c *Conference) TouchPost(tx *sqlx.Tx, u *User, lastPost time.Time) (*ConferenceSettings, error) {
|
||||
cs, err := c.Settings(u)
|
||||
func (c *Conference) TouchPost(ctx context.Context, tx *sqlx.Tx, u *User, lastPost time.Time) (*ConferenceSettings, error) {
|
||||
cs, err := c.Settings(ctx, u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !u.IsAnon { // anon user can't update squat
|
||||
if cs == nil {
|
||||
ci, cerr := u.ContactInfo()
|
||||
ci, cerr := u.ContactInfo(ctx)
|
||||
if cerr != nil {
|
||||
return nil, cerr
|
||||
}
|
||||
@@ -217,10 +218,10 @@ func (c *Conference) TouchPost(tx *sqlx.Tx, u *User, lastPost time.Time) (*Confe
|
||||
LastRead: &lastPost,
|
||||
LastPost: &lastPost,
|
||||
}
|
||||
_, err = tx.Exec("INSERT INTO confsettings (confid, uid, default_pseud, last_read, last_post) VALUES (?, ?, ?, ?, ?)",
|
||||
_, err = tx.ExecContext(ctx, "INSERT INTO confsettings (confid, uid, default_pseud, last_read, last_post) VALUES (?, ?, ?, ?, ?)",
|
||||
c.ConfId, u.Uid, defaultPseud, lastPost, lastPost)
|
||||
} else {
|
||||
_, err = tx.Exec("UPDATE confsettings SET last_post = ? WHERE confid = ? AND uid = ?", lastPost, c.ConfId, u.Uid)
|
||||
_, err = tx.ExecContext(ctx, "UPDATE confsettings SET last_post = ? WHERE confid = ? AND uid = ?", lastPost, c.ConfId, u.Uid)
|
||||
cs.LastPost = &lastPost
|
||||
}
|
||||
if err != nil {
|
||||
@@ -232,19 +233,20 @@ func (c *Conference) TouchPost(tx *sqlx.Tx, u *User, lastPost time.Time) (*Confe
|
||||
|
||||
/* AmGetConference returns a conference given its ID.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* id - The ID of the conference.
|
||||
* Returns:
|
||||
* Pointer to the conference, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetConference(id int32) (*Conference, error) {
|
||||
func AmGetConference(ctx context.Context, id int32) (*Conference, error) {
|
||||
var err error = nil
|
||||
getConferenceMutex.Lock()
|
||||
defer getConferenceMutex.Unlock()
|
||||
rc, ok := conferenceCache.Get(id)
|
||||
if !ok {
|
||||
var dbdata []Conference
|
||||
err = amdb.Select(&dbdata, "SELECT * from confs where confid = ?", id)
|
||||
err = amdb.SelectContext(ctx, &dbdata, "SELECT * from confs where confid = ?", id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -261,18 +263,19 @@ func AmGetConference(id int32) (*Conference, error) {
|
||||
|
||||
/* AmGetConferenceByAlias returns a conference given its alias.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* alias - The alias to look up.
|
||||
* Returns:
|
||||
* Pointer to the conference, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetConferenceByAlias(alias string) (*Conference, error) {
|
||||
func AmGetConferenceByAlias(ctx context.Context, alias string) (*Conference, error) {
|
||||
var confid int32
|
||||
xconf, ok := conferenceAliasMap.Load(alias)
|
||||
if ok {
|
||||
confid = xconf.(int32)
|
||||
} else {
|
||||
rs, err := amdb.Query("SELECT confid FROM confalias WHERE alias = ?", alias)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT confid FROM confalias WHERE alias = ?", alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -282,19 +285,20 @@ func AmGetConferenceByAlias(alias string) (*Conference, error) {
|
||||
rs.Scan(&confid)
|
||||
conferenceAliasMap.Store(alias, confid)
|
||||
}
|
||||
return AmGetConference(confid)
|
||||
return AmGetConference(ctx, confid)
|
||||
}
|
||||
|
||||
/* AmGetConferenceByAliasInCommunity returns a conference in a community given its alias.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* cid - The community to look inside.
|
||||
* alias - The alias to look up.
|
||||
* Returns:
|
||||
* Pointer to the conference, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetConferenceByAliasInCommunity(cid int32, alias string) (*Conference, error) {
|
||||
rs, err := amdb.Query(`SELECT c.confid FROM commtoconf c, confalias a WHERE c.confid = a.confid
|
||||
func AmGetConferenceByAliasInCommunity(ctx context.Context, cid int32, alias string) (*Conference, error) {
|
||||
rs, err := amdb.QueryContext(ctx, `SELECT c.confid FROM commtoconf c, confalias a WHERE c.confid = a.confid
|
||||
AND c.commid = ? AND a.alias = ?`, cid, alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -304,23 +308,24 @@ func AmGetConferenceByAliasInCommunity(cid int32, alias string) (*Conference, er
|
||||
}
|
||||
var confid int32
|
||||
rs.Scan(&confid)
|
||||
return AmGetConference(confid)
|
||||
return AmGetConference(ctx, confid)
|
||||
}
|
||||
|
||||
/* AmGetCommunityConferences returns all conferences for a given community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* cid - Community ID to get conferences for.
|
||||
* showHidden - true to show hidden conferences.
|
||||
* Returns:
|
||||
* Array containing the COnference pointers, or nil.
|
||||
* Stanbard Go error status.
|
||||
*/
|
||||
func AmGetCommunityConferences(cid int32, showHidden bool) ([]*Conference, error) {
|
||||
func AmGetCommunityConferences(ctx context.Context, cid int32, showHidden bool) ([]*Conference, error) {
|
||||
q := ""
|
||||
if !showHidden {
|
||||
q = " AND x.hide_list = 0"
|
||||
}
|
||||
rs, err := amdb.Query(`SELECT x.confid FROM commtoconf x, confs c WHERE x.confid = c.confid
|
||||
rs, err := amdb.QueryContext(ctx, `SELECT x.confid FROM commtoconf x, confs c WHERE x.confid = c.confid
|
||||
AND x.commid = ?`+q+" ORDER BY x.sequence, c.name", cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -329,7 +334,7 @@ func AmGetCommunityConferences(cid int32, showHidden bool) ([]*Conference, error
|
||||
for rs.Next() {
|
||||
var confid int32
|
||||
rs.Scan(&confid)
|
||||
conf, err := AmGetConference(confid)
|
||||
conf, err := AmGetConference(ctx, confid)
|
||||
if err == nil {
|
||||
rc = append(rc, conf)
|
||||
}
|
||||
|
||||
+19
-15
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
@@ -51,9 +52,9 @@ type ContactInfo struct {
|
||||
}
|
||||
|
||||
// lookupCommunityContact looks up the ID of a contact for a community.
|
||||
func lookupCommunityContact(id int32) (int32, error) {
|
||||
func lookupCommunityContact(ctx context.Context, id int32) (int32, error) {
|
||||
var rc int32 = -1
|
||||
rs, err := amdb.Query("SELECT contactid FROM contacts WHERE owner_commid = ?", id)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT contactid FROM contacts WHERE owner_commid = ?", id)
|
||||
if err == nil {
|
||||
if rs.Next() {
|
||||
rs.Scan(&rc)
|
||||
@@ -63,9 +64,9 @@ func lookupCommunityContact(id int32) (int32, error) {
|
||||
}
|
||||
|
||||
// lookupUserContact looks up the ID of a contact for a user.
|
||||
func lookupUserContact(uid int32) (int32, error) {
|
||||
func lookupUserContact(ctx context.Context, uid int32) (int32, error) {
|
||||
var rc int32 = -1
|
||||
rs, err := amdb.Query("SELECT contactid FROM contacts WHERE owner_uid = ? AND owner_commid = -1", uid)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT contactid FROM contacts WHERE owner_uid = ? AND owner_commid = -1", uid)
|
||||
if err == nil {
|
||||
if rs.Next() {
|
||||
rs.Scan(&rc)
|
||||
@@ -114,11 +115,13 @@ func (ci *ContactInfo) FullName(ps bool) string {
|
||||
}
|
||||
|
||||
/* Save saves the contact info to the database.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* 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) {
|
||||
func (ci *ContactInfo) Save(ctx context.Context) (bool, error) {
|
||||
ci.Mutex.Lock()
|
||||
defer ci.Mutex.Unlock()
|
||||
|
||||
@@ -129,9 +132,9 @@ func (ci *ContactInfo) Save() (bool, error) {
|
||||
var nx int32
|
||||
var err error
|
||||
if ci.OwnerCommId > 0 {
|
||||
nx, err = lookupCommunityContact(ci.OwnerCommId)
|
||||
nx, err = lookupCommunityContact(ctx, ci.OwnerCommId)
|
||||
} else {
|
||||
nx, err = lookupUserContact(ci.OwnerUid)
|
||||
nx, err = lookupUserContact(ctx, ci.OwnerUid)
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -147,7 +150,7 @@ func (ci *ContactInfo) Save() (bool, error) {
|
||||
}
|
||||
if !emailChange {
|
||||
// we don't THINK the E-mail address is changing, but we could be wrong...
|
||||
rs, err := amdb.Query("SELECT contactid FROM contacts WHERE contactid = ? AND email = ?", ci.ContactId, ci.Email)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT contactid FROM contacts WHERE contactid = ? AND email = ?", ci.ContactId, ci.Email)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -157,7 +160,7 @@ func (ci *ContactInfo) Save() (bool, error) {
|
||||
}
|
||||
// Handle the database heavy lifting.
|
||||
if updateMode {
|
||||
_, err := amdb.NamedExec(`UPDATE contacts SET given_name = :given_name, family_name = :family_name, middle_init = :middle_init,
|
||||
_, err := amdb.NamedExecContext(ctx, `UPDATE contacts SET given_name = :given_name, family_name = :family_name, middle_init = :middle_init,
|
||||
prefix = :prefix, suffix = :suffix, company = :company, addr1 = :addr1, addr2 = :addr2, locality = :locality, region = :region,
|
||||
pcode = :pcode, country = :country, phone = :phone, fax = :fax, mobile = :mobile, email = :email, pvt_addr = :pvt_addr,
|
||||
pvt_phone = :pvt_phone, pvt_fax = :pvt_fax, pvt_email = :pvt_email, photo_url = :photo_url, url = :url, lastupdate = NOW()
|
||||
@@ -167,7 +170,7 @@ func (ci *ContactInfo) Save() (bool, error) {
|
||||
}
|
||||
contactCache.Add(ci.ContactId, ci)
|
||||
} else {
|
||||
res, err := amdb.NamedExec(`INSERT INTO contacts (given_name, family_name, middle_init, prefix, suffix, company, addr1,
|
||||
res, err := amdb.NamedExecContext(ctx, `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 (:given_name, :family_name, :middle_init, :prefix, :suffix, :company, :addr1, :addr2, :locality,
|
||||
@@ -181,7 +184,7 @@ func (ci *ContactInfo) Save() (bool, error) {
|
||||
contactCache.Add(ci.ContactId, ci)
|
||||
}
|
||||
// Refresh the last update date.
|
||||
rs, err := amdb.Query("SELECT lastupdate FROM contacts WHERE contactid = ?", ci.ContactId)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT lastupdate FROM contacts WHERE contactid = ?", ci.ContactId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -241,9 +244,9 @@ func init() {
|
||||
}
|
||||
|
||||
// internalContactInfo retrieves the contact info from the database.
|
||||
func internalContactInfo(id int32) (*ContactInfo, error) {
|
||||
func internalContactInfo(ctx context.Context, id int32) (*ContactInfo, error) {
|
||||
var dbdata []ContactInfo
|
||||
err := amdb.Select(&dbdata, "SELECT * from contacts WHERE contactid = ?", id)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * from contacts WHERE contactid = ?", id)
|
||||
if err == nil {
|
||||
if len(dbdata) > 1 {
|
||||
err = fmt.Errorf("internalContactInfo(%d): Too many responses (%d)", id, len(dbdata))
|
||||
@@ -258,19 +261,20 @@ func internalContactInfo(id int32) (*ContactInfo, error) {
|
||||
|
||||
/* AmGetContactInfo retrieves the contact info for a given identifier.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* id - The contact info ID top retrieve.
|
||||
* Returns:
|
||||
* ContactInfo retrieved, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetContactInfo(id int32) (*ContactInfo, error) {
|
||||
func AmGetContactInfo(ctx context.Context, id int32) (*ContactInfo, error) {
|
||||
getContactMutex.Lock()
|
||||
defer getContactMutex.Unlock()
|
||||
rc, ok := contactCache.Get(id)
|
||||
if ok {
|
||||
return rc.(*ContactInfo), nil
|
||||
}
|
||||
rc2, err := internalContactInfo(id)
|
||||
rc2, err := internalContactInfo(ctx, id)
|
||||
if err == nil {
|
||||
if rc2 != nil {
|
||||
contactCache.Add(id, rc2)
|
||||
|
||||
@@ -9,15 +9,18 @@
|
||||
// The database package contains database management and storage logic.
|
||||
package database
|
||||
|
||||
import "context"
|
||||
|
||||
/* AmIsEmailAddressBanned returns true if the given E-mail address is on the "banned" list.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* address - The E-mail address to be checked.
|
||||
* Returns:
|
||||
* true if the address is banned, false if not.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmIsEmailAddressBanned(address string) (bool, error) {
|
||||
rs, err := amdb.Query("SELECT by_uid FROM emailban WHERE address = ?", address)
|
||||
func AmIsEmailAddressBanned(ctx context.Context, address string) (bool, error) {
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT by_uid FROM emailban WHERE address = ?", address)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
+15
-12
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
@@ -60,11 +61,11 @@ var globalProps map[int32]string = make(map[int32]string)
|
||||
var globalPropMutex sync.Mutex
|
||||
|
||||
// Flags returns the global flags.
|
||||
func (g *Globals) Flags() (*util.OptionSet, error) {
|
||||
func (g *Globals) Flags(ctx context.Context) (*util.OptionSet, error) {
|
||||
g.Mutex.Lock()
|
||||
defer g.Mutex.Unlock()
|
||||
if g.flags == nil {
|
||||
s, err := AmGetGlobalProperty(GlobalPropFlags)
|
||||
s, err := AmGetGlobalProperty(ctx, GlobalPropFlags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -74,11 +75,11 @@ func (g *Globals) Flags() (*util.OptionSet, error) {
|
||||
}
|
||||
|
||||
// SaveFlags saves off the global flags.
|
||||
func (g *Globals) SaveFlags(f *util.OptionSet) error {
|
||||
func (g *Globals) SaveFlags(ctx context.Context, f *util.OptionSet) error {
|
||||
s := f.AsString()
|
||||
g.Mutex.Lock()
|
||||
defer g.Mutex.Unlock()
|
||||
err := AmSetGlobalProperty(GlobalPropFlags, s)
|
||||
err := AmSetGlobalProperty(ctx, GlobalPropFlags, s)
|
||||
if err == nil {
|
||||
g.flags = f
|
||||
}
|
||||
@@ -86,12 +87,12 @@ func (g *Globals) SaveFlags(f *util.OptionSet) error {
|
||||
}
|
||||
|
||||
// AmGlobals returns trhe pointer to the singleton Globals instance.
|
||||
func AmGlobals() (*Globals, error) {
|
||||
func AmGlobals(ctx context.Context) (*Globals, error) {
|
||||
globalsMutex.Lock()
|
||||
defer globalsMutex.Unlock()
|
||||
if theGlobals == nil {
|
||||
var dbdata []Globals
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM globals")
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * FROM globals")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -105,17 +106,18 @@ func AmGlobals() (*Globals, error) {
|
||||
|
||||
/* AmGetGlobalProperty returns the value of a global property.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* index - The index of the property to retrieve.
|
||||
* Returns:
|
||||
* Value of the property, or empty string.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetGlobalProperty(index int32) (string, error) {
|
||||
func AmGetGlobalProperty(ctx context.Context, index int32) (string, error) {
|
||||
globalPropMutex.Lock()
|
||||
defer globalPropMutex.Unlock()
|
||||
rc, ok := globalProps[index]
|
||||
if !ok {
|
||||
rs, err := amdb.Query("SELECT data FROM propglobal WHERE ndx = ?", index)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT data FROM propglobal WHERE ndx = ?", index)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -131,17 +133,18 @@ func AmGetGlobalProperty(index int32) (string, error) {
|
||||
|
||||
/* AmSetGlobalProperty sets the value of a global property.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* index - The index of the property to set.
|
||||
* value - The value of the property to set.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmSetGlobalProperty(index int32, value string) error {
|
||||
func AmSetGlobalProperty(ctx context.Context, index int32, value string) error {
|
||||
globalPropMutex.Lock()
|
||||
defer globalPropMutex.Unlock()
|
||||
_, updateMode := globalProps[index]
|
||||
if !updateMode {
|
||||
rs, err := amdb.Query("SELECT data FROM propglobal WHERE ndx = ?", index)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT data FROM propglobal WHERE ndx = ?", index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -149,9 +152,9 @@ func AmSetGlobalProperty(index int32, value string) error {
|
||||
}
|
||||
var err error = nil
|
||||
if updateMode {
|
||||
_, err = amdb.Exec("UPDATE propglobal SET data = ? WHERE ndx = ?", value, index)
|
||||
_, err = amdb.ExecContext(ctx, "UPDATE propglobal SET data = ? WHERE ndx = ?", value, index)
|
||||
} else {
|
||||
_, err = amdb.Exec("INSERT INTO propglobal (ndx, data) VALUES (?, ?)", index, value)
|
||||
_, err = amdb.ExecContext(ctx, "INSERT INTO propglobal (ndx, data) VALUES (?, ?)", index, value)
|
||||
}
|
||||
if err == nil {
|
||||
globalProps[index] = value
|
||||
|
||||
+15
-11
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
@@ -31,14 +32,14 @@ const (
|
||||
)
|
||||
|
||||
// Save persists the ImageStore record to the database.
|
||||
func (img *ImageStore) Save() error {
|
||||
func (img *ImageStore) Save(ctx context.Context) error {
|
||||
var err error
|
||||
if img.ImgId > 0 {
|
||||
_, err = amdb.NamedExec(`UPDATE imagestore SET typecode = :typecode, ownerid = :ownerid, mimetype = :mimetype,
|
||||
_, err = amdb.NamedExecContext(ctx, `UPDATE imagestore SET typecode = :typecode, ownerid = :ownerid, mimetype = :mimetype,
|
||||
length = :length, data = :data WHERE imgid = :imgid`, img)
|
||||
} else {
|
||||
var rs sql.Result
|
||||
rs, err = amdb.NamedExec(`INSERT INTO imagestore (typecode, ownerid, mimetype, length, data)
|
||||
rs, err = amdb.NamedExecContext(ctx, `INSERT INTO imagestore (typecode, ownerid, mimetype, length, data)
|
||||
VALUES (:typecode, :ownerid, :mimetype, :length, :data)`, img)
|
||||
if err == nil {
|
||||
var lii int64
|
||||
@@ -53,14 +54,15 @@ func (img *ImageStore) Save() error {
|
||||
|
||||
/* AmLoadImage loads an image from the database.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* id - The ID of the image to be loaded.
|
||||
* Returns:
|
||||
* Pointer to ImageStore, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmLoadImage(id int32) (*ImageStore, error) {
|
||||
func AmLoadImage(ctx context.Context, id int32) (*ImageStore, error) {
|
||||
var dbdata []ImageStore
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM imagestore WHERE imgid = ?", id)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * FROM imagestore WHERE imgid = ?", id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -74,6 +76,7 @@ func AmLoadImage(id int32) (*ImageStore, error) {
|
||||
|
||||
/* AmStoreImage stores an image in the database, overwriting one with the same type code and owner if it exists.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* typecode - Type code for the image.
|
||||
* owner - Owner Id for the image (UID or community ID)
|
||||
* mimetype - MIME type of the image.
|
||||
@@ -82,8 +85,8 @@ func AmLoadImage(id int32) (*ImageStore, error) {
|
||||
* Pointer to ImageStore, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmStoreImage(typecode int16, owner int32, mimetype string, data []byte) (*ImageStore, error) {
|
||||
rs, err := amdb.Query("SELECT imgid FROM imagestore WHERE typecode = ? AND ownerid = ?", typecode, owner)
|
||||
func AmStoreImage(ctx context.Context, typecode int16, owner int32, mimetype string, data []byte) (*ImageStore, error) {
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT imgid FROM imagestore WHERE typecode = ? AND ownerid = ?", typecode, owner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -91,7 +94,7 @@ func AmStoreImage(typecode int16, owner int32, mimetype string, data []byte) (*I
|
||||
if rs.Next() {
|
||||
var id int32
|
||||
rs.Scan(&id)
|
||||
img, err = AmLoadImage(id)
|
||||
img, err = AmLoadImage(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -108,7 +111,7 @@ func AmStoreImage(typecode int16, owner int32, mimetype string, data []byte) (*I
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
err = img.Save()
|
||||
err = img.Save(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -117,11 +120,12 @@ func AmStoreImage(typecode int16, owner int32, mimetype string, data []byte) (*I
|
||||
|
||||
/* AmDeleteImage erases an image from the database.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* id - The ID of the image to be deleted.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmDeleteImage(id int32) error {
|
||||
_, err := amdb.Exec("DELETE FROM imagestore WHERE imgid = ?", id)
|
||||
func AmDeleteImage(ctx context.Context, id int32) error {
|
||||
_, err := amdb.ExecContext(ctx, "DELETE FROM imagestore WHERE imgid = ?", id)
|
||||
return err
|
||||
}
|
||||
|
||||
+4
-3
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
@@ -40,12 +41,13 @@ func init() {
|
||||
|
||||
/* AmTestIPBan tests an IP address to see if it's on the banned list.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context parameter.
|
||||
* ip_address - The IP address to be tested.
|
||||
* Returns:
|
||||
* Ban message if the address is banned, or empty string if it isn't.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmTestIPBan(ip_address string) (string, error) {
|
||||
func AmTestIPBan(ctx context.Context, ip_address string) (string, error) {
|
||||
banMutex.Lock()
|
||||
defer banMutex.Unlock()
|
||||
rc := knownBans[ip_address]
|
||||
@@ -63,8 +65,7 @@ func AmTestIPBan(ip_address string) (string, error) {
|
||||
iv.SetBytes(addr)
|
||||
iv_lo := big.NewInt(0).And(iv, low64mask).Uint64()
|
||||
iv_hi := big.NewInt(0).Rsh(iv, 64).Uint64()
|
||||
rows, err := amdb.Query(`
|
||||
SELECT message FROM ipban WHERE (address_lo & mask_lo) = (? & mask_lo)
|
||||
rows, err := amdb.QueryContext(ctx, `SELECT message FROM ipban WHERE (address_lo & mask_lo) = (? & mask_lo)
|
||||
AND (address_hi & mask_hi) = (? & mask_hi) AND (expire IS NULL OR expire >= ?)
|
||||
AND enable <> 0 ORDER BY mask_hi DESC, mask_lo DESC`, iv_lo, iv_hi, time.Now().UTC())
|
||||
if err != nil {
|
||||
|
||||
+10
-8
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
@@ -43,6 +44,7 @@ func (p *PostHeader) IsScribbled() bool {
|
||||
|
||||
/* SetAttachment sets the attachment data for a post.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* fileName - Name of the original attachment file.
|
||||
* mimeType - MIME type of the attachment data.
|
||||
* length - Length of the attachment data in bytes.
|
||||
@@ -50,16 +52,16 @@ func (p *PostHeader) IsScribbled() bool {
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (p *PostHeader) SetAttachment(fileName string, mimeType string, length int32, data []byte) error {
|
||||
_, err := amdb.Exec("INSERT INTO postattach (postid, datalen, filename, mimetype, data) VALUES (?, ?, ?, ?, ?)",
|
||||
func (p *PostHeader) SetAttachment(ctx context.Context, fileName string, mimeType string, length int32, data []byte) error {
|
||||
_, err := amdb.ExecContext(ctx, "INSERT INTO postattach (postid, datalen, filename, mimetype, data) VALUES (?, ?, ?, ?, ?)",
|
||||
p.PostId, length, fileName, mimeType, data)
|
||||
return err
|
||||
}
|
||||
|
||||
// Text returns the text associated with a post.
|
||||
func (p *PostHeader) Text() (string, error) {
|
||||
func (p *PostHeader) Text(ctx context.Context) (string, error) {
|
||||
var dbdata []PostData
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM postdata WHERE postid = ?", p.PostId)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * FROM postdata WHERE postid = ?", p.PostId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -72,9 +74,9 @@ func (p *PostHeader) Text() (string, error) {
|
||||
return *dbdata[0].Data, nil
|
||||
}
|
||||
|
||||
func AmGetPost(postId int64) (*PostHeader, error) {
|
||||
func AmGetPost(ctx context.Context, postId int64) (*PostHeader, error) {
|
||||
var dbdata []PostHeader
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM posts WHERE postid = ?", postId)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * FROM posts WHERE postid = ?", postId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -87,9 +89,9 @@ func AmGetPost(postId int64) (*PostHeader, error) {
|
||||
return &(dbdata[0]), nil
|
||||
}
|
||||
|
||||
func AmGetPostRange(topic *Topic, first, last int32) ([]PostHeader, error) {
|
||||
func AmGetPostRange(ctx context.Context, topic *Topic, first, last int32) ([]PostHeader, error) {
|
||||
var rc []PostHeader
|
||||
err := amdb.Select(&rc, "SELECT * FROM posts WHERE topicid = ? AND num >= ? AND num <= ? ORDER BY num", topic.TopicId, first, last)
|
||||
err := amdb.SelectContext(ctx, &rc, "SELECT * FROM posts WHERE topicid = ? AND num >= ? AND num <= ? ORDER BY num", topic.TopicId, first, last)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -32,9 +33,9 @@ func (d *PostLinkData) NeedsDBVerification() bool {
|
||||
}
|
||||
|
||||
// VerifyNames verifies the post link data against the database.
|
||||
func (d *PostLinkData) VerifyNames() error {
|
||||
func (d *PostLinkData) VerifyNames(ctx context.Context) error {
|
||||
if d.Community != "" {
|
||||
comm, err := AmGetCommunityByAlias(d.Community)
|
||||
comm, err := AmGetCommunityByAlias(ctx, d.Community)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -43,7 +44,7 @@ func (d *PostLinkData) VerifyNames() error {
|
||||
}
|
||||
}
|
||||
if d.Conference != "" {
|
||||
conf, err := AmGetConferenceByAlias(d.Conference)
|
||||
conf, err := AmGetConferenceByAlias(ctx, d.Conference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+34
-27
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"slices"
|
||||
"sync"
|
||||
@@ -21,28 +22,28 @@ import (
|
||||
|
||||
// ServiceVTable is a serioes of functions called for services on specific events.
|
||||
type ServiceVTable interface {
|
||||
OnNewCommunity(*sqlx.Tx, *Community) error
|
||||
OnDeleteCommunity(*sqlx.Tx, int32) error
|
||||
OnUserJoinCommunity(*sqlx.Tx, *Community, *User) error
|
||||
OnUserLeaveCommunity(*sqlx.Tx, *Community, *User) error
|
||||
OnNewCommunity(context.Context, *sqlx.Tx, *Community) error
|
||||
OnDeleteCommunity(context.Context, *sqlx.Tx, int32) error
|
||||
OnUserJoinCommunity(context.Context, *sqlx.Tx, *Community, *User) error
|
||||
OnUserLeaveCommunity(context.Context, *sqlx.Tx, *Community, *User) error
|
||||
}
|
||||
|
||||
// emptyServiceVTable is a default ServiceVTable that does nothing.
|
||||
type emptyServiceVTable struct{}
|
||||
|
||||
func (*emptyServiceVTable) OnNewCommunity(*sqlx.Tx, *Community) error {
|
||||
func (*emptyServiceVTable) OnNewCommunity(context.Context, *sqlx.Tx, *Community) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*emptyServiceVTable) OnDeleteCommunity(*sqlx.Tx, int32) error {
|
||||
func (*emptyServiceVTable) OnDeleteCommunity(context.Context, *sqlx.Tx, int32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*emptyServiceVTable) OnUserJoinCommunity(*sqlx.Tx, *Community, *User) error {
|
||||
func (*emptyServiceVTable) OnUserJoinCommunity(context.Context, *sqlx.Tx, *Community, *User) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*emptyServiceVTable) OnUserLeaveCommunity(*sqlx.Tx, *Community, *User) error {
|
||||
func (*emptyServiceVTable) OnUserLeaveCommunity(context.Context, *sqlx.Tx, *Community, *User) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -124,17 +125,18 @@ func init() {
|
||||
|
||||
/* AmGetCommunityServices returns all the community service definitions for a community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* cid - Community ID to get services for.
|
||||
* Returns:
|
||||
* Array of ServiceDef pointers for the community's services.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetCommunityServices(cid int32) ([]*ServiceDef, error) {
|
||||
func AmGetCommunityServices(ctx context.Context, cid int32) ([]*ServiceDef, error) {
|
||||
servicesCacheMutex.Lock()
|
||||
defer servicesCacheMutex.Unlock()
|
||||
rc, ok := servicesCache.Get(cid)
|
||||
if !ok {
|
||||
rs, err := amdb.Query("SELECT ftr_code FROM commftrs WHERE commid = ?", cid)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT ftr_code FROM commftrs WHERE commid = ?", cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -153,18 +155,19 @@ func AmGetCommunityServices(cid int32) ([]*ServiceDef, error) {
|
||||
|
||||
/* AmGetCommunityServices returns all the community service definitions for a community, using a transaction.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* tx - Transaction to be used.
|
||||
* cid - Community ID to get services for.
|
||||
* Returns:
|
||||
* Array of ServiceDef pointers for the community's services.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetCommunityServicesTx(tx *sqlx.Tx, cid int32) ([]*ServiceDef, error) {
|
||||
func AmGetCommunityServicesTx(ctx context.Context, tx *sqlx.Tx, cid int32) ([]*ServiceDef, error) {
|
||||
servicesCacheMutex.Lock()
|
||||
defer servicesCacheMutex.Unlock()
|
||||
rc, ok := servicesCache.Get(cid)
|
||||
if !ok {
|
||||
rs, err := tx.Query("SELECT ftr_code FROM commftrs WHERE commid = ?", cid)
|
||||
rs, err := tx.QueryContext(ctx, "SELECT ftr_code FROM commftrs WHERE commid = ?", cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -184,17 +187,18 @@ func AmGetCommunityServicesTx(tx *sqlx.Tx, cid int32) ([]*ServiceDef, error) {
|
||||
/* AmEstablishCommunityServices establishes the service (feature) records for a new community,
|
||||
* and allows the services to establish themselves.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* tx - The transaction to use.
|
||||
* c - The new community.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmEstablishCommunityServices(tx *sqlx.Tx, c *Community) error {
|
||||
func AmEstablishCommunityServices(ctx context.Context, tx *sqlx.Tx, c *Community) error {
|
||||
dom := serviceRoot.byName["community"]
|
||||
a := make([]*ServiceDef, 0, len(dom.Services))
|
||||
for i, svc := range dom.Services {
|
||||
if svc.Default {
|
||||
_, err := tx.Exec("INSERT INTO commftrs (commid, ftr_code) VALUES (?, ?)", c.Id, svc.Index)
|
||||
_, err := tx.ExecContext(ctx, "INSERT INTO commftrs (commid, ftr_code) VALUES (?, ?)", c.Id, svc.Index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -205,7 +209,7 @@ func AmEstablishCommunityServices(tx *sqlx.Tx, c *Community) error {
|
||||
servicesCache.Add(c.Id, a)
|
||||
servicesCacheMutex.Unlock()
|
||||
for _, svc := range a {
|
||||
err := svc.vtable.OnNewCommunity(tx, c)
|
||||
err := svc.vtable.OnNewCommunity(ctx, tx, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -216,23 +220,24 @@ func AmEstablishCommunityServices(tx *sqlx.Tx, c *Community) error {
|
||||
/* AmDeleteCommunityServices cleans up all services associated with a community that has gone away,
|
||||
* and then cleans up the service records.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* tx - The transaction to use.
|
||||
* cid - The ID of the departing community.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmDeleteCommunityServices(tx *sqlx.Tx, cid int32) error {
|
||||
arr, err := AmGetCommunityServices(cid)
|
||||
func AmDeleteCommunityServices(ctx context.Context, tx *sqlx.Tx, cid int32) error {
|
||||
arr, err := AmGetCommunityServices(ctx, cid)
|
||||
if err == nil {
|
||||
for _, svc := range arr {
|
||||
err = svc.vtable.OnDeleteCommunity(tx, cid)
|
||||
err = svc.vtable.OnDeleteCommunity(ctx, tx, cid)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
_, err = tx.Exec("DELETE FROM commftrs WHERE commid = ?", cid)
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM commftrs WHERE commid = ?", cid)
|
||||
servicesCacheMutex.Lock()
|
||||
servicesCache.Remove(cid)
|
||||
servicesCacheMutex.Unlock()
|
||||
@@ -242,17 +247,18 @@ func AmDeleteCommunityServices(tx *sqlx.Tx, cid int32) error {
|
||||
|
||||
/* AmOnUserJoinCommunityServices gives services a chance to update themselves when a user joins a community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* tx - The current database transaction.
|
||||
* c - The community that is being joined.
|
||||
* u - The user leaving that community.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmOnUserJoinCommunityServices(tx *sqlx.Tx, c *Community, u *User) error {
|
||||
arr, err := AmGetCommunityServicesTx(tx, c.Id)
|
||||
func AmOnUserJoinCommunityServices(ctx context.Context, tx *sqlx.Tx, c *Community, u *User) error {
|
||||
arr, err := AmGetCommunityServicesTx(ctx, tx, c.Id)
|
||||
if err == nil {
|
||||
for _, svc := range arr {
|
||||
err = svc.vtable.OnUserJoinCommunity(tx, c, u)
|
||||
err = svc.vtable.OnUserJoinCommunity(ctx, tx, c, u)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
@@ -263,17 +269,18 @@ func AmOnUserJoinCommunityServices(tx *sqlx.Tx, c *Community, u *User) error {
|
||||
|
||||
/* AmOnUserLeaveCommunityServices gives services a chance to update themselves when a user leaves a community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* tx - The current database transaction.
|
||||
* c - The community that is being left.
|
||||
* u - The user leaving that community.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmOnUserLeaveCommunityServices(tx *sqlx.Tx, c *Community, u *User) error {
|
||||
arr, err := AmGetCommunityServicesTx(tx, c.Id)
|
||||
func AmOnUserLeaveCommunityServices(ctx context.Context, tx *sqlx.Tx, c *Community, u *User) error {
|
||||
arr, err := AmGetCommunityServicesTx(ctx, tx, c.Id)
|
||||
if err == nil {
|
||||
for _, svc := range arr {
|
||||
err = svc.vtable.OnUserLeaveCommunity(tx, c, u)
|
||||
err = svc.vtable.OnUserLeaveCommunity(ctx, tx, c, u)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
@@ -282,8 +289,8 @@ func AmOnUserLeaveCommunityServices(tx *sqlx.Tx, c *Community, u *User) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func AmTestService(c *Community, serviceId string) (bool, error) {
|
||||
arr, err := AmGetCommunityServices(c.Id)
|
||||
func AmTestService(ctx context.Context, c *Community, serviceId string) (bool, error) {
|
||||
arr, err := AmGetCommunityServices(ctx, c.Id)
|
||||
if err == nil {
|
||||
for _, svc := range arr {
|
||||
if svc.Id == serviceId {
|
||||
|
||||
+11
-6
@@ -9,7 +9,11 @@
|
||||
// The database package contains database management and storage logic.
|
||||
package database
|
||||
|
||||
import "github.com/jmoiron/sqlx"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type Sidebox struct {
|
||||
Uid int32 `db:"uid"`
|
||||
@@ -19,12 +23,12 @@ type Sidebox struct {
|
||||
}
|
||||
|
||||
// copySideboxes copies sideboxes from one user to another.
|
||||
func copySideboxes(tx *sqlx.Tx, toUid int32, fromUid int32) error {
|
||||
func copySideboxes(ctx context.Context, tx *sqlx.Tx, toUid int32, fromUid int32) error {
|
||||
sbox := make([]Sidebox, 0, 3)
|
||||
err := tx.Select(&sbox, "SELECT * from sideboxes WHERE uid = ?", fromUid)
|
||||
err := tx.SelectContext(ctx, &sbox, "SELECT * from sideboxes WHERE uid = ?", fromUid)
|
||||
if err == nil {
|
||||
for _, sb := range sbox {
|
||||
_, err := tx.Exec("INSERT INTO sideboxes (uid, boxid, sequence, param) VALUES (?, ?, ?, ?)", toUid, sb.Boxid, sb.Sequence, sb.Param)
|
||||
_, err := tx.ExecContext(ctx, "INSERT INTO sideboxes (uid, boxid, sequence, param) VALUES (?, ?, ?, ?)", toUid, sb.Boxid, sb.Sequence, sb.Param)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
@@ -35,13 +39,14 @@ func copySideboxes(tx *sqlx.Tx, toUid int32, fromUid int32) error {
|
||||
|
||||
/* AmGetSideboxes returns all the configured sideboxes for a user.
|
||||
* Parameters:
|
||||
* ctx = Standard Go context value.
|
||||
* uid = The ID of the user to retrieve sideboxes for.
|
||||
* Returns:
|
||||
* Array of Sidebox structures for the user, or nil
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmGetSideboxes(uid int32) ([]*Sidebox, error) {
|
||||
func AmGetSideboxes(ctx context.Context, uid int32) ([]*Sidebox, error) {
|
||||
sboxes := make([]*Sidebox, 0, 3)
|
||||
err := amdb.Select(&sboxes, "SELECT * FROM sideboxes WHERE uid = ? ORDER BY SEQUENCE", uid)
|
||||
err := amdb.SelectContext(ctx, &sboxes, "SELECT * FROM sideboxes WHERE uid = ? ORDER BY SEQUENCE", uid)
|
||||
return sboxes, err
|
||||
}
|
||||
|
||||
+33
-26
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
@@ -34,12 +35,12 @@ type Topic struct {
|
||||
}
|
||||
|
||||
// GetPost returns a post in the topic by number.
|
||||
func (t *Topic) GetPost(num int32) (*PostHeader, error) {
|
||||
func (t *Topic) GetPost(ctx context.Context, num int32) (*PostHeader, error) {
|
||||
if num > t.TopMessage {
|
||||
return nil, fmt.Errorf("no post %d in topic %d", num, t.TopicId)
|
||||
}
|
||||
var dbdata []PostHeader
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM posts WHERE topicid = ? AND num = ?", t.TopicId, num)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * FROM posts WHERE topicid = ? AND num = ?", t.TopicId, num)
|
||||
if err == nil {
|
||||
if len(dbdata) == 0 {
|
||||
err = fmt.Errorf("no post %d in topic %d", num, t.TopicId)
|
||||
@@ -53,8 +54,8 @@ func (t *Topic) GetPost(num int32) (*PostHeader, error) {
|
||||
}
|
||||
|
||||
// GetLastRead returns the "last read" message for a user on a topic.
|
||||
func (t *Topic) GetLastRead(u *User) (int32, error) {
|
||||
rs, err := amdb.Query("SELECT last_message FROM topicsettings WHERE topicid = ? AND uid = ?", t.TopicId, u.Uid)
|
||||
func (t *Topic) GetLastRead(ctx context.Context, u *User) (int32, error) {
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT last_message FROM topicsettings WHERE topicid = ? AND uid = ?", t.TopicId, u.Uid)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
@@ -66,12 +67,14 @@ func (t *Topic) GetLastRead(u *User) (int32, error) {
|
||||
}
|
||||
|
||||
// SetLastRead sets the "last read" message for a user on a topic.
|
||||
func (t *Topic) SetLastRead(u *User, postNum int32) error {
|
||||
rs, err := amdb.Exec("UPDATE topicsettings SET last_message = ?, last_read = NOW() WHERE topicid = ? AND uid = ?", postNum, t.TopicId, u.Uid)
|
||||
func (t *Topic) SetLastRead(ctx context.Context, u *User, postNum int32) error {
|
||||
rs, err := amdb.ExecContext(ctx, "UPDATE topicsettings SET last_message = ?, last_read = NOW() WHERE topicid = ? AND uid = ?",
|
||||
postNum, t.TopicId, u.Uid)
|
||||
if err == nil {
|
||||
nrow, _ := rs.RowsAffected()
|
||||
if nrow == 0 {
|
||||
_, err = amdb.Exec("INSERT INTO topicsettings (topicid, uid, last_message, last_read, last_post) VALUES (?, ?, ?, NOW(), NULL)", t.TopicId, u.Uid, postNum)
|
||||
_, err = amdb.ExecContext(ctx, "INSERT INTO topicsettings (topicid, uid, last_message, last_read, last_post) VALUES (?, ?, ?, NOW(), NULL)",
|
||||
t.TopicId, u.Uid, postNum)
|
||||
}
|
||||
}
|
||||
return err
|
||||
@@ -104,14 +107,15 @@ type TopicSummary struct {
|
||||
|
||||
/* AmGetTopic retrieves a topic by ID.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* topicId - ID of the topic to retrieve.
|
||||
* Returns:
|
||||
* The topic pointer, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetTopic(topicId int32) (*Topic, error) {
|
||||
func AmGetTopic(ctx context.Context, topicId int32) (*Topic, error) {
|
||||
var dbdata []Topic
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM topics WHERE topicid = ?", topicId)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * FROM topics WHERE topicid = ?", topicId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -126,15 +130,16 @@ func AmGetTopic(topicId int32) (*Topic, error) {
|
||||
|
||||
/* AmGetTopicTx retrieves a topic by ID, in a transaction.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* tx - The transaction to use.
|
||||
* topicId - ID of the topic to retrieve.
|
||||
* Returns:
|
||||
* The topic pointer, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetTopicTx(tx *sqlx.Tx, topicId int32) (*Topic, error) {
|
||||
func AmGetTopicTx(ctx context.Context, tx *sqlx.Tx, topicId int32) (*Topic, error) {
|
||||
var dbdata []Topic
|
||||
err := tx.Select(&dbdata, "SELECT * FROM topics WHERE topicid = ?", topicId)
|
||||
err := tx.SelectContext(ctx, &dbdata, "SELECT * FROM topics WHERE topicid = ?", topicId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -149,15 +154,16 @@ func AmGetTopicTx(tx *sqlx.Tx, topicId int32) (*Topic, error) {
|
||||
|
||||
/* AmGetTopicByNumber retrieves a topic by conference and sequence number.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* conf - The conference to look in.
|
||||
* topicNum - The topic number within that conference.
|
||||
* Returns:
|
||||
* Pointer to the Topic, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetTopicByNumber(conf *Conference, topicNum int16) (*Topic, error) {
|
||||
func AmGetTopicByNumber(ctx context.Context, conf *Conference, topicNum int16) (*Topic, error) {
|
||||
var dbdata []Topic
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM topics WHERE confid = ? AND num = ?", conf.ConfId, topicNum)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * FROM topics WHERE confid = ? AND num = ?", conf.ConfId, topicNum)
|
||||
if err == nil {
|
||||
if len(dbdata) == 0 {
|
||||
err = fmt.Errorf("no topic numbered %d in conference %s (#%d)", topicNum, conf.Name, conf.ConfId)
|
||||
@@ -189,6 +195,7 @@ const (
|
||||
|
||||
/* AmListTopics produces a list of topic summary information according to specific options.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* confid - The ID of the conference to list topics in.
|
||||
* uid - The UID of the user to consider the settings of.
|
||||
* viewOption - One of the following constants:
|
||||
@@ -210,7 +217,7 @@ const (
|
||||
* List of TopicSummary pointers.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmListTopics(confid int32, uid int32, viewOption int, sortOption int, ignoreSticky bool) ([]*TopicSummary, error) {
|
||||
func AmListTopics(ctx context.Context, confid int32, uid int32, viewOption int, sortOption int, ignoreSticky bool) ([]*TopicSummary, error) {
|
||||
// Decode the viewOption into a WHERE clause.
|
||||
var whereClause string
|
||||
switch viewOption {
|
||||
@@ -296,7 +303,7 @@ func AmListTopics(confid int32, uid int32, viewOption int, sortOption int, ignor
|
||||
fullStatement.WriteString(orderByClause)
|
||||
|
||||
// Execute and capture results
|
||||
rs, err := amdb.Query(fullStatement.String(), uid, confid)
|
||||
rs, err := amdb.QueryContext(ctx, fullStatement.String(), uid, confid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -310,7 +317,7 @@ func AmListTopics(confid int32, uid int32, viewOption int, sortOption int, ignor
|
||||
return rc, nil
|
||||
}
|
||||
|
||||
func AmNewTopic(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, ipaddr string) (*Topic, error) {
|
||||
var ar *AuditRecord = nil
|
||||
defer func() {
|
||||
@@ -325,16 +332,16 @@ func AmNewTopic(conf *Conference, user *User, title string, zeroPostPseud string
|
||||
}()
|
||||
|
||||
unlock := true
|
||||
tx.Exec("LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, posts WRITE, postdata WRITE;")
|
||||
tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, posts WRITE, postdata WRITE;")
|
||||
defer func() {
|
||||
if unlock {
|
||||
tx.Exec("UNLOCK TABLES;")
|
||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
||||
}
|
||||
}()
|
||||
|
||||
// Insert the new topic into the database.
|
||||
conf.Mutex.Lock()
|
||||
rs, err := tx.Exec("INSERT INTO topics (confid, num, creator_uid, createdate, lastupdate, name) VALUES (?, ?, ?, NOW(), NOW(), ?)",
|
||||
rs, err := tx.ExecContext(ctx, "INSERT INTO topics (confid, num, creator_uid, createdate, lastupdate, name) VALUES (?, ?, ?, NOW(), NOW(), ?)",
|
||||
conf.ConfId, conf.TopTopic+1, user.Uid, title)
|
||||
if err != nil {
|
||||
conf.Mutex.Unlock()
|
||||
@@ -347,14 +354,14 @@ func AmNewTopic(conf *Conference, user *User, title string, zeroPostPseud string
|
||||
return nil, err
|
||||
}
|
||||
// Get the topic.
|
||||
topic, err := AmGetTopicTx(tx, int32(xid))
|
||||
topic, err := AmGetTopicTx(ctx, tx, int32(xid))
|
||||
if err != nil {
|
||||
conf.Mutex.Unlock()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update the conference to set the last update and top topic.
|
||||
_, err = tx.Exec("UPDATE confs SET lastupdate = ?, top_topic = ? WHERE confid = ?", topic.CreateDate, conf.TopTopic+1, conf.ConfId)
|
||||
_, err = tx.ExecContext(ctx, "UPDATE confs SET lastupdate = ?, top_topic = ? WHERE confid = ?", topic.CreateDate, conf.TopTopic+1, conf.ConfId)
|
||||
if err != nil {
|
||||
conf.Mutex.Unlock()
|
||||
return nil, err
|
||||
@@ -364,7 +371,7 @@ func AmNewTopic(conf *Conference, user *User, title string, zeroPostPseud string
|
||||
conf.Mutex.Unlock()
|
||||
|
||||
// Add the "header record" for the first post.
|
||||
rs, err = tx.Exec("INSERT INTO posts (topicid, num, linecount, creator_uid, posted, pseud) VALUES (?, 0, ?, ?, ?, ?)",
|
||||
rs, err = tx.ExecContext(ctx, "INSERT INTO posts (topicid, num, linecount, creator_uid, posted, pseud) VALUES (?, 0, ?, ?, ?, ?)",
|
||||
topic.TopicId, zeroPostLines, user.Uid, topic.CreateDate, zeroPostPseud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -374,23 +381,23 @@ func AmNewTopic(conf *Conference, user *User, title string, zeroPostPseud string
|
||||
return nil, err
|
||||
}
|
||||
// Add the post data.
|
||||
_, err = tx.Exec("INSERT INTO postdata (postid, data) VALUES (?, ?)", int32(xid), zeroPost)
|
||||
_, err = tx.ExecContext(ctx, "INSERT INTO postdata (postid, data) VALUES (?, ?)", int32(xid), zeroPost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add a new topic settings record for the user, too.
|
||||
_, err = tx.Exec("INSERT INTO topicsettings (topicid, uid, last_post) VALUES (?, ?, ?)",
|
||||
_, err = tx.ExecContext(ctx, "INSERT INTO topicsettings (topicid, uid, last_post) VALUES (?, ?, ?)",
|
||||
topic.TopicId, user.Uid, topic.CreateDate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx.Exec("UNLOCK TABLES;")
|
||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
||||
unlock = false
|
||||
|
||||
// update the "last posted" date in the conference settings
|
||||
_, err = conf.TouchPost(tx, user, topic.CreateDate)
|
||||
_, err = conf.TouchPost(ctx, tx, user, topic.CreateDate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+90
-75
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
@@ -53,11 +54,11 @@ func (p *UserPrefs) Clone() *UserPrefs {
|
||||
}
|
||||
|
||||
// Save saves off the user preferences, replacing the prefs on the user if necessary.
|
||||
func (p *UserPrefs) Save(u *User) error {
|
||||
func (p *UserPrefs) Save(ctx context.Context, u *User) error {
|
||||
if u != nil && u.Uid != p.Uid {
|
||||
return errors.New("internal mismatch of IDs")
|
||||
}
|
||||
_, err := amdb.NamedExec("UPDATE userprefs SET localeid = :localeid, tzid = :tzid WHERE uid = :uid", p)
|
||||
_, err := amdb.NamedExecContext(ctx, "UPDATE userprefs SET localeid = :localeid, tzid = :tzid WHERE uid = :uid", p)
|
||||
if err == nil && u != nil {
|
||||
u.prefs = p
|
||||
}
|
||||
@@ -181,27 +182,27 @@ func init() {
|
||||
}
|
||||
|
||||
// ContactInfo returns the contact info structure for the user.
|
||||
func (u *User) ContactInfo() (*ContactInfo, error) {
|
||||
func (u *User) ContactInfo(ctx context.Context) (*ContactInfo, error) {
|
||||
if u.ContactID < 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return AmGetContactInfo(u.ContactID)
|
||||
return AmGetContactInfo(ctx, u.ContactID)
|
||||
}
|
||||
|
||||
// ContactInfo returns the contact info structure for the user, quietly.
|
||||
func (u *User) ContactInfoQ() *ContactInfo {
|
||||
func (u *User) ContactInfoQ(ctx context.Context) *ContactInfo {
|
||||
if u.ContactID < 0 {
|
||||
return nil
|
||||
}
|
||||
ci, _ := AmGetContactInfo(u.ContactID)
|
||||
ci, _ := AmGetContactInfo(ctx, u.ContactID)
|
||||
return ci
|
||||
}
|
||||
|
||||
// SetContactID sets the contact ID of a user.
|
||||
func (u *User) SetContactID(cid int32) error {
|
||||
func (u *User) SetContactID(ctx context.Context, cid int32) error {
|
||||
u.Mutex.Lock()
|
||||
defer u.Mutex.Unlock()
|
||||
if _, err := amdb.Exec("UPDATE users SET contactid = ? WHERE uid = ?", cid, u.Uid); err != nil {
|
||||
if _, err := amdb.ExecContext(ctx, "UPDATE users SET contactid = ? WHERE uid = ?", cid, u.Uid); err != nil {
|
||||
return err
|
||||
}
|
||||
u.ContactID = cid
|
||||
@@ -213,14 +214,14 @@ func (u *User) SetContactID(cid int32) error {
|
||||
* Authentication token value
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (u *User) NewAuthToken() (string, error) {
|
||||
func (u *User) NewAuthToken(ctx context.Context) (string, error) {
|
||||
if u.IsAnon {
|
||||
return "", errors.New("cannot generate token for anonymous user")
|
||||
}
|
||||
u.Mutex.Lock()
|
||||
defer u.Mutex.Unlock()
|
||||
newToken := util.GenerateRandomAuthString()
|
||||
if _, err := amdb.Exec("UPDATE users SET tokenauth = ? WHERE uid = ?", newToken, u.Uid); err != nil {
|
||||
if _, err := amdb.ExecContext(ctx, "UPDATE users SET tokenauth = ? WHERE uid = ?", newToken, u.Uid); err != nil {
|
||||
return "", err
|
||||
}
|
||||
u.Tokenauth = &newToken
|
||||
@@ -230,12 +231,13 @@ func (u *User) NewAuthToken() (string, error) {
|
||||
|
||||
/* ConfirmEMailAddress checks the E-mail confirmation number and sets "verified" status if it's OK.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* confnum - The entered confirmation number.
|
||||
* remoteIP - The remote IP address for audit messages.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (u *User) ConfirmEMailAddress(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)
|
||||
@@ -260,12 +262,12 @@ func (u *User) ConfirmEMailAddress(confnum int32, remoteIP string) error {
|
||||
ar = AmNewAudit(AuditVerifyEmailFail, u.Uid, remoteIP, "Invalid confirmation number")
|
||||
return errors.New("confirmation number is incorrect. Please try again")
|
||||
}
|
||||
_, err := tx.Exec("UPDATE users SET verify_email = 1, base_lvl = ? WHERE uid = ?",
|
||||
_, err := tx.ExecContext(ctx, "UPDATE users SET verify_email = 1, base_lvl = ? WHERE uid = ?",
|
||||
AmDefaultRole("Global.AfterVerify").Level(), u.Uid)
|
||||
if err == nil {
|
||||
u.VerifyEMail = true
|
||||
u.BaseLevel = AmDefaultRole("Global.AfterVerify").Level()
|
||||
err = AmAutoJoinCommunities(tx, u)
|
||||
err = AmAutoJoinCommunities(ctx, tx, u)
|
||||
if err == nil {
|
||||
err = tx.Commit()
|
||||
if err == nil {
|
||||
@@ -278,11 +280,11 @@ func (u *User) ConfirmEMailAddress(confnum int32, remoteIP string) error {
|
||||
}
|
||||
|
||||
// NewEmailConfirmationNumber creates a new confirmation number for a user and saves it off.
|
||||
func (u *User) NewEmailConfirmationNumber() error {
|
||||
func (u *User) NewEmailConfirmationNumber(ctx context.Context) error {
|
||||
u.Mutex.Lock()
|
||||
defer u.Mutex.Unlock()
|
||||
newnum := util.GenerateRandomConfirmationNumber()
|
||||
_, err := amdb.Exec("UPDATE users SET email_confnum = ? WHERE uid = ?", newnum, u.Uid)
|
||||
_, err := amdb.ExecContext(ctx, "UPDATE users SET email_confnum = ? WHERE uid = ?", newnum, u.Uid)
|
||||
if err != nil {
|
||||
u.EmailConfNum = newnum
|
||||
}
|
||||
@@ -290,7 +292,7 @@ func (u *User) NewEmailConfirmationNumber() error {
|
||||
}
|
||||
|
||||
// ChangePassword resets a user's password.
|
||||
func (u *User) ChangePassword(password string, remoteIP string) error {
|
||||
func (u *User) ChangePassword(ctx context.Context, password string, remoteIP string) error {
|
||||
var ar *AuditRecord = nil
|
||||
defer func() {
|
||||
AmStoreAudit(ar)
|
||||
@@ -299,7 +301,7 @@ func (u *User) ChangePassword(password string, remoteIP string) error {
|
||||
u.Mutex.Lock()
|
||||
defer u.Mutex.Unlock()
|
||||
pval := hashPassword(password)
|
||||
_, err := amdb.Exec("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 {
|
||||
u.Passhash = pval
|
||||
ar = AmNewAudit(AuditChangePassword, u.Uid, remoteIP, "via password change request")
|
||||
@@ -308,11 +310,11 @@ func (u *User) ChangePassword(password string, remoteIP string) error {
|
||||
}
|
||||
|
||||
// GetFlags retrieves the flags from the properties.
|
||||
func (u *User) Flags() (*util.OptionSet, error) {
|
||||
func (u *User) Flags(ctx context.Context) (*util.OptionSet, error) {
|
||||
u.Mutex.Lock()
|
||||
defer u.Mutex.Unlock()
|
||||
if u.flags == nil {
|
||||
s, err := AmGetUserProperty(u.Uid, UserPropFlags)
|
||||
s, err := AmGetUserProperty(ctx, u.Uid, UserPropFlags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -325,11 +327,11 @@ func (u *User) Flags() (*util.OptionSet, error) {
|
||||
}
|
||||
|
||||
// SaveFlags writes the flags to the database and stores them.
|
||||
func (u *User) SaveFlags(f *util.OptionSet) error {
|
||||
func (u *User) SaveFlags(ctx context.Context, f *util.OptionSet) error {
|
||||
s := f.AsString()
|
||||
u.Mutex.Lock()
|
||||
defer u.Mutex.Unlock()
|
||||
err := AmSetUserProperty(u.Uid, UserPropFlags, &s)
|
||||
err := AmSetUserProperty(ctx, u.Uid, UserPropFlags, &s)
|
||||
if err == nil {
|
||||
u.flags = f
|
||||
}
|
||||
@@ -337,8 +339,8 @@ func (u *User) SaveFlags(f *util.OptionSet) error {
|
||||
}
|
||||
|
||||
// FlagValue returns the boolean value of one of the user flags.
|
||||
func (u *User) FlagValue(ndx uint) bool {
|
||||
f, err := u.Flags()
|
||||
func (u *User) FlagValue(ctx context.Context, ndx uint) bool {
|
||||
f, err := u.Flags(ctx)
|
||||
if err != nil {
|
||||
log.Errorf("flag retrieval error for user %d: %v", u.Uid, err)
|
||||
return false
|
||||
@@ -347,12 +349,12 @@ func (u *User) FlagValue(ndx uint) bool {
|
||||
}
|
||||
|
||||
// Prefs returns the user's preferences record.
|
||||
func (u *User) Prefs() (*UserPrefs, error) {
|
||||
func (u *User) Prefs(ctx context.Context) (*UserPrefs, error) {
|
||||
u.Mutex.Lock()
|
||||
defer u.Mutex.Unlock()
|
||||
if u.prefs == nil {
|
||||
var dbdata []UserPrefs
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM userprefs WHERE uid = ?", u.Uid)
|
||||
err := amdb.SelectContext(ctx, &dbdata, "SELECT * FROM userprefs WHERE uid = ?", u.Uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -366,13 +368,14 @@ func (u *User) Prefs() (*UserPrefs, error) {
|
||||
|
||||
/* SetProfileData sets the "profile" variables for this user.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* reminder - Password reminder string.
|
||||
* dob - Date of birth field.
|
||||
* descr - Description string.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (u *User) SetProfileData(reminder string, dob *time.Time, descr *string) error {
|
||||
func (u *User) SetProfileData(ctx context.Context, reminder string, dob *time.Time, descr *string) error {
|
||||
u.Mutex.Lock()
|
||||
defer u.Mutex.Unlock()
|
||||
_, err := amdb.Exec("UPDATE users SET passreminder = ?, dob = ?, description = ? WHERE uid = ?", reminder, dob, descr, u.Uid)
|
||||
@@ -386,19 +389,20 @@ func (u *User) SetProfileData(reminder string, dob *time.Time, descr *string) er
|
||||
|
||||
/* AmGetUser returns a reference to the specified user.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* uid - The UID of the user.
|
||||
* Returns:
|
||||
* Pointer to User containing user data, or nil
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmGetUser(uid int32) (*User, error) {
|
||||
func AmGetUser(ctx context.Context, uid int32) (*User, error) {
|
||||
var err error = nil
|
||||
getUserMutex.Lock()
|
||||
defer getUserMutex.Unlock()
|
||||
rc, ok := userCache.Get(uid)
|
||||
if !ok {
|
||||
var dbdata []User
|
||||
err = amdb.Select(&dbdata, "SELECT * from users WHERE uid = ?", uid)
|
||||
err = amdb.SelectContext(ctx, &dbdata, "SELECT * from users WHERE uid = ?", uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -413,20 +417,21 @@ func AmGetUser(uid int32) (*User, error) {
|
||||
|
||||
/* AmGetUserTx returns a reference to the specified user inside a transaction.
|
||||
* Parameters:
|
||||
* ctxt - Standard Go context value.
|
||||
* tx - The transaction we're in.
|
||||
* uid - The UID of the user.
|
||||
* Returns:
|
||||
* Pointer to User containing user data, or nil
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmGetUserTx(tx *sqlx.Tx, uid int32) (*User, error) {
|
||||
func AmGetUserTx(ctx context.Context, tx *sqlx.Tx, uid int32) (*User, error) {
|
||||
var err error = nil
|
||||
getUserMutex.Lock()
|
||||
defer getUserMutex.Unlock()
|
||||
rc, ok := userCache.Get(uid)
|
||||
if !ok {
|
||||
var dbdata []User
|
||||
err = tx.Select(&dbdata, "SELECT * from users WHERE uid = ?", uid)
|
||||
err = tx.SelectContext(ctx, &dbdata, "SELECT * from users WHERE uid = ?", uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -441,19 +446,20 @@ func AmGetUserTx(tx *sqlx.Tx, uid int32) (*User, error) {
|
||||
|
||||
/* AmGetUserByName returns a reference to the specified user.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* name - The username of the user.
|
||||
* tx - If this is not nil, use this transaction.
|
||||
* Returns:
|
||||
* Pointer to User containing user data, or nil
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmGetUserByName(name string, tx *sqlx.Tx) (*User, error) {
|
||||
func AmGetUserByName(ctx context.Context, name string, tx *sqlx.Tx) (*User, error) {
|
||||
var dbdata []User
|
||||
var err error
|
||||
if tx != nil {
|
||||
err = tx.Select(&dbdata, "SELECT * FROM users WHERE username = ?", name)
|
||||
err = tx.SelectContext(ctx, &dbdata, "SELECT * FROM users WHERE username = ?", name)
|
||||
} else {
|
||||
err = amdb.Select(&dbdata, "SELECT * FROM users WHERE username = ?", name)
|
||||
err = amdb.SelectContext(ctx, &dbdata, "SELECT * FROM users WHERE username = ?", name)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -472,9 +478,9 @@ func AmGetUserByName(name string, tx *sqlx.Tx) (*User, error) {
|
||||
}
|
||||
|
||||
// getAnonUserID retrieves the UID of the "anonymous" user from the database.
|
||||
func getAnonUserID() (int32, error) {
|
||||
func getAnonUserID(ctx context.Context) (int32, error) {
|
||||
if anonUid < 0 {
|
||||
rows, err := amdb.Query("SELECT uid FROM users WHERE is_anon = 1")
|
||||
rows, err := amdb.QueryContext(ctx, "SELECT uid FROM users WHERE is_anon = 1")
|
||||
if err == nil {
|
||||
defer rows.Close()
|
||||
if rows.Next() {
|
||||
@@ -495,26 +501,29 @@ func getAnonUserID() (int32, error) {
|
||||
|
||||
/* AmIsUserAnon returns true if the specified user ID is the anonymous one.
|
||||
* Parameters:
|
||||
* ctx = Standard Go context value.
|
||||
* uid = The user ID to test.
|
||||
* Returns:
|
||||
* true if the user is anonymous, false if not
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmIsUserAnon(uid int32) (bool, error) {
|
||||
auid, err := getAnonUserID()
|
||||
func AmIsUserAnon(ctx context.Context, uid int32) (bool, error) {
|
||||
auid, err := getAnonUserID(ctx)
|
||||
return (uid == auid), err
|
||||
}
|
||||
|
||||
/* AmGetAnonUser returns a reference to the anonymous user.
|
||||
* Parameters:
|
||||
* ctx = Standard Go context value.
|
||||
* Returns:
|
||||
* Pointer to User containing anonymous user data, or nil
|
||||
* Standard Go error status
|
||||
*/
|
||||
func AmGetAnonUser() (*User, error) {
|
||||
func AmGetAnonUser(ctx context.Context) (*User, error) {
|
||||
var rc *User = nil
|
||||
auid, err := getAnonUserID()
|
||||
auid, err := getAnonUserID(ctx)
|
||||
if err == nil {
|
||||
rc, err = AmGetUser(auid)
|
||||
rc, err = AmGetUser(ctx, auid)
|
||||
}
|
||||
return rc, err
|
||||
}
|
||||
@@ -531,16 +540,17 @@ func hashPassword(password string) string {
|
||||
}
|
||||
|
||||
// touchUser updates the last access time for the user.
|
||||
func touchUser(tx *sqlx.Tx, user *User) {
|
||||
func touchUser(ctx context.Context, tx *sqlx.Tx, user *User) {
|
||||
user.Mutex.Lock()
|
||||
defer user.Mutex.Unlock()
|
||||
moment := time.Now().UTC()
|
||||
tx.Exec("UPDATE user SET lastaccess = ? WHERE uid = ?", moment, user.Uid)
|
||||
tx.ExecContext(ctx, "UPDATE user SET lastaccess = ? WHERE uid = ?", moment, user.Uid)
|
||||
user.LastAccess = &moment
|
||||
}
|
||||
|
||||
/* AmAuthenticateUser authenticates a user by name and password.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context parameter.
|
||||
* name - The user name to try.
|
||||
* password - The password to try.
|
||||
* remote_ip - The remote IP address, for audit records.
|
||||
@@ -548,8 +558,8 @@ func touchUser(tx *sqlx.Tx, user *User) {
|
||||
* The User pointer if authenticated, or nil if not.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmAuthenticateUser(name string, password string, remoteIP string) (*User, error) {
|
||||
log.Debugf("AmAuthenicate() authenticating user %s...", name)
|
||||
func AmAuthenticateUser(ctx context.Context, name string, password string, remoteIP string) (*User, error) {
|
||||
log.Debugf("AmAuthenticateUser() authenticating user %s...", name)
|
||||
var ar *AuditRecord = nil
|
||||
defer func() {
|
||||
AmStoreAudit(ar)
|
||||
@@ -562,7 +572,7 @@ func AmAuthenticateUser(name string, password string, remoteIP string) (*User, e
|
||||
}
|
||||
}()
|
||||
|
||||
user, err := AmGetUserByName(name, tx)
|
||||
user, err := AmGetUserByName(ctx, name, tx)
|
||||
if err != nil {
|
||||
log.Error("...user not found")
|
||||
ar = AmNewAudit(AuditLoginFail, 0, remoteIP, fmt.Sprintf("Bad username: %s", name))
|
||||
@@ -585,7 +595,7 @@ func AmAuthenticateUser(name string, password string, remoteIP string) (*User, e
|
||||
return nil, errors.New("the password you have specified is incorrect; please try again")
|
||||
}
|
||||
log.Debug("...authenticated")
|
||||
touchUser(tx, user)
|
||||
touchUser(ctx, tx, user)
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -621,13 +631,14 @@ func crackAuthString(authString string) (int32, string, error) {
|
||||
|
||||
/* AmAuthenticateUserByToken authenticates a user via the stored cookie authentication string.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* authString - The stored cookie authentication string.
|
||||
* remoteIP - The remote IP address wheter trhe user is logging in from.
|
||||
* Returns:
|
||||
* Pointer to the authenticated User, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmAuthenticateUserByToken(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)
|
||||
@@ -645,7 +656,7 @@ func AmAuthenticateUserByToken(authString string, remoteIP string) (*User, error
|
||||
return nil, fmt.Errorf("authString not valid, ignored: %v", err)
|
||||
}
|
||||
var user *User
|
||||
user, err = AmGetUserTx(tx, uid)
|
||||
user, err = AmGetUserTx(ctx, tx, uid)
|
||||
if err != nil {
|
||||
log.Error("...user not found")
|
||||
ar = AmNewAudit(AuditLoginFail, 0, remoteIP, fmt.Sprintf("Bad uid: %d", uid))
|
||||
@@ -668,7 +679,7 @@ func AmAuthenticateUserByToken(authString string, remoteIP string) (*User, error
|
||||
return nil, errors.New("token mismatch")
|
||||
}
|
||||
log.Debug("...authenticated")
|
||||
touchUser(tx, user)
|
||||
touchUser(ctx, tx, user)
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -680,6 +691,7 @@ func AmAuthenticateUserByToken(authString string, remoteIP string) (*User, error
|
||||
|
||||
/* AmCreateNewUser creates a new user record in the database.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* username - New user name.
|
||||
* password - New password.
|
||||
* reminder - Password reminder string.
|
||||
@@ -689,12 +701,12 @@ func AmAuthenticateUserByToken(authString string, remoteIP string) (*User, error
|
||||
* Pointer to new user record.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmCreateNewUser(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, _ := getAnonUserID()
|
||||
anon, _ := getAnonUserID(ctx)
|
||||
success := false
|
||||
tx := amdb.MustBegin()
|
||||
defer func() {
|
||||
@@ -703,15 +715,15 @@ func AmCreateNewUser(username string, password string, reminder string, dob *tim
|
||||
}
|
||||
}()
|
||||
unlock := true
|
||||
tx.Exec("LOCK TABLES users WRITE, userprefs WRITE, propuser WRITE, commmember WRITE, sideboxes WRITE, confhotlist WRITE;")
|
||||
tx.ExecContext(ctx, "LOCK TABLES users WRITE, userprefs WRITE, propuser WRITE, commmember WRITE, sideboxes WRITE, confhotlist WRITE;")
|
||||
defer func() {
|
||||
if unlock {
|
||||
tx.Exec("UNLOCK TABLES;")
|
||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
||||
}
|
||||
}()
|
||||
|
||||
// Test if the user name is already taken.
|
||||
rs, err := tx.Query("SELECT uid FROM users WHERE username = ?", username)
|
||||
rs, err := tx.QueryContext(ctx, "SELECT uid FROM users WHERE username = ?", username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if rs.Next() {
|
||||
@@ -720,7 +732,7 @@ func AmCreateNewUser(username string, password string, reminder string, dob *tim
|
||||
}
|
||||
|
||||
// Insert the user record.
|
||||
_, err2 := tx.Exec(`INSERT INTO users (username, passhash, verify_email, lockout, email_confnum,
|
||||
_, err2 := tx.ExecContext(ctx, `INSERT INTO users (username, passhash, verify_email, lockout, email_confnum,
|
||||
base_lvl, created, lastaccess, passreminder, description, dob) VALUES (?, ?, 0, 0, ?, ?, NOW(), NOW(), ?, '', ?)`,
|
||||
username, hashPassword(password), util.GenerateRandomConfirmationNumber(), AmDefaultRole("Global.NewUser").Level(),
|
||||
reminder, dob)
|
||||
@@ -728,42 +740,42 @@ func AmCreateNewUser(username string, password string, reminder string, dob *tim
|
||||
return nil, err2
|
||||
}
|
||||
// Read back the user, which also puts it in the cache.
|
||||
user, err3 := AmGetUserByName(username, tx)
|
||||
user, err3 := AmGetUserByName(ctx, username, tx)
|
||||
if err3 != nil {
|
||||
return nil, err3
|
||||
}
|
||||
log.Debugf("...created new user \"%s\" with UID %d", username, user.Uid)
|
||||
|
||||
// add user preferences
|
||||
_, err = tx.Exec("INSERT INTO userprefs (uid) VALUES (?)", user.Uid)
|
||||
_, err = tx.ExecContext(ctx, "INSERT INTO userprefs (uid) VALUES (?)", user.Uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// add user properties
|
||||
props := make([]UserProperties, 0)
|
||||
err = tx.Select(&props, "SELECT * FROM propuser WHERE uid = ?", anon)
|
||||
err = tx.SelectContext(ctx, &props, "SELECT * FROM propuser WHERE uid = ?", anon)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, p := range props {
|
||||
_, err := tx.Exec("INSERT INTO propuser (uid, ndx, data) VALUES (?, ?, ?)", user.Uid, p.Index, p.Data)
|
||||
_, err := tx.ExecContext(ctx, "INSERT INTO propuser (uid, ndx, data) VALUES (?, ?, ?)", user.Uid, p.Index, p.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// add user sideboxes
|
||||
err = copySideboxes(tx, user.Uid, anon)
|
||||
err = copySideboxes(ctx, tx, user.Uid, anon)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx.Exec("UNLOCK TABLES;")
|
||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
||||
unlock = false
|
||||
|
||||
// auto-join communities
|
||||
err = AmAutoJoinCommunities(tx, user)
|
||||
err = AmAutoJoinCommunities(ctx, tx, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -782,7 +794,7 @@ func AmCreateNewUser(username string, password string, reminder string, dob *tim
|
||||
}
|
||||
|
||||
// internalGetProp is a helper used by the property functions.
|
||||
func internalGetProp(uid int32, ndx int32) (*UserProperties, error) {
|
||||
func internalGetProp(ctx context.Context, uid int32, ndx int32) (*UserProperties, error) {
|
||||
var err error = nil
|
||||
key := fmt.Sprintf("%d:%d", uid, ndx)
|
||||
getUserPropMutex.Lock()
|
||||
@@ -790,7 +802,7 @@ func internalGetProp(uid int32, ndx int32) (*UserProperties, error) {
|
||||
rc, ok := userPropCache.Get(key)
|
||||
if !ok {
|
||||
var dbdata []UserProperties
|
||||
err = amdb.Select(&dbdata, "SELECT * from propuser WHERE uid = ? AND ndx = ?", uid, ndx)
|
||||
err = amdb.SelectContext(ctx, &dbdata, "SELECT * from propuser WHERE uid = ? AND ndx = ?", uid, ndx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -808,14 +820,15 @@ func internalGetProp(uid int32, ndx int32) (*UserProperties, error) {
|
||||
|
||||
/* AmGetUserProperty retrieves the value of a user property.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* uid - The UID of the user to get the property for.
|
||||
* ndx - The index of the property to retrieve.
|
||||
* Returns:
|
||||
* Value of the property string.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmGetUserProperty(uid int32, ndx int32) (*string, error) {
|
||||
p, err := internalGetProp(uid, ndx)
|
||||
func AmGetUserProperty(ctx context.Context, uid int32, ndx int32) (*string, error) {
|
||||
p, err := internalGetProp(ctx, uid, ndx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -824,27 +837,28 @@ func AmGetUserProperty(uid int32, ndx int32) (*string, error) {
|
||||
|
||||
/* AmSetUserProperty sets the value of a user property.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* uid - The UID of the user to set the property for.
|
||||
* ndx - The index of the property to set.
|
||||
* val - The new value of the property.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmSetUserProperty(uid int32, ndx int32, val *string) error {
|
||||
p, err := internalGetProp(uid, ndx)
|
||||
func AmSetUserProperty(ctx context.Context, uid int32, ndx int32, val *string) error {
|
||||
p, err := internalGetProp(ctx, uid, ndx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
getUserPropMutex.Lock()
|
||||
defer getUserPropMutex.Unlock()
|
||||
if p != nil {
|
||||
_, err = amdb.Exec("UPDATE propuser SET data = ? WHERE uid = ? AND ndx = ?", val, uid, ndx)
|
||||
_, err = amdb.ExecContext(ctx, "UPDATE propuser SET data = ? WHERE uid = ? AND ndx = ?", val, uid, ndx)
|
||||
if err == nil {
|
||||
p.Data = val
|
||||
}
|
||||
} else {
|
||||
prop := UserProperties{Uid: uid, Index: ndx, Data: val}
|
||||
_, err := amdb.NamedExec("INSERT INTO propuser (uid, ndx, data) VALUES(:uid, :ndx, :data)", prop)
|
||||
_, err := amdb.NamedExecContext(ctx, "INSERT INTO propuser (uid, ndx, data) VALUES(:uid, :ndx, :data)", prop)
|
||||
if err == nil {
|
||||
userPropCache.Add(fmt.Sprintf("%d:%d", uid, ndx), prop)
|
||||
}
|
||||
@@ -854,6 +868,7 @@ func AmSetUserProperty(uid int32, ndx int32, val *string) error {
|
||||
|
||||
/* AmSearchUsers searches for users matching certain criteria.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* field - A value indicating which field to search:
|
||||
* SearchUserFieldName - The user name.
|
||||
* SearchUserFieldDescription - The user description.
|
||||
@@ -871,7 +886,7 @@ func AmSetUserProperty(uid int32, ndx int32, val *string) error {
|
||||
* The total number of users matching this query (could be greater than max)
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmSearchUsers(field int, oper int, term string, offset int, max int) ([]*User, int, error) {
|
||||
func AmSearchUsers(ctx context.Context, field int, oper int, term string, offset int, max int) ([]*User, int, error) {
|
||||
var queryPortion strings.Builder
|
||||
switch field {
|
||||
case SearchUserFieldName:
|
||||
@@ -902,7 +917,7 @@ func AmSearchUsers(field int, oper int, term string, offset int, max int) ([]*Us
|
||||
return nil, -1, errors.New("invalid operator selector")
|
||||
}
|
||||
q := queryPortion.String()
|
||||
rs, err := amdb.Query("SELECT COUNT(*) FROM users u, contacts c WHERE u.contactid = c.contactid AND u.is_anon = 0 AND " + q)
|
||||
rs, err := amdb.QueryContext(ctx, "SELECT COUNT(*) FROM users u, contacts c WHERE u.contactid = c.contactid AND u.is_anon = 0 AND "+q)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
@@ -915,10 +930,10 @@ func AmSearchUsers(field int, oper int, term string, offset int, max int) ([]*Us
|
||||
return make([]*User, 0), 0, nil
|
||||
}
|
||||
if offset > 0 {
|
||||
rs, err = amdb.Query("SELECT u.uid FROM users u, contacts c WHERE u.contactid = c.contactid AND u.is_anon = 0 AND "+q+
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT u.uid FROM users u, contacts c WHERE u.contactid = c.contactid AND u.is_anon = 0 AND "+q+
|
||||
" ORDER BY u.username LIMIT ? OFFSET ?", max, offset)
|
||||
} else {
|
||||
rs, err = amdb.Query("SELECT u.uid FROM users u, contacts c WHERE u.contactid = c.contactid AND u.is_anon = 0 AND "+q+
|
||||
rs, err = amdb.QueryContext(ctx, "SELECT u.uid FROM users u, contacts c WHERE u.contactid = c.contactid AND u.is_anon = 0 AND "+q+
|
||||
" ORDER BY u.username LIMIT ?", max)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -928,7 +943,7 @@ func AmSearchUsers(field int, oper int, term string, offset int, max int) ([]*Us
|
||||
for rs.Next() {
|
||||
var uid int32
|
||||
rs.Scan(&uid)
|
||||
u, err := AmGetUser(uid)
|
||||
u, err := AmGetUser(ctx, uid)
|
||||
if err == nil {
|
||||
rc = append(rc, u)
|
||||
}
|
||||
|
||||
+4
-3
@@ -12,6 +12,7 @@ package email
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -47,7 +48,7 @@ var mailHost string
|
||||
var auth smtp.Auth
|
||||
|
||||
// formatMessage takes a message and turns it into serialized bytes for sending.
|
||||
func formatMessage(m *amMessage) ([]byte, error) {
|
||||
func formatMessage(ctx context.Context, m *amMessage) ([]byte, error) {
|
||||
if m.template != "" {
|
||||
// Render the template for the message, which may reset Subject.
|
||||
templ, err := emailRenderer.GetTemplate(m.template)
|
||||
@@ -62,7 +63,7 @@ func formatMessage(m *amMessage) ([]byte, error) {
|
||||
return make([]byte, 0), err
|
||||
}
|
||||
}
|
||||
user, err := database.AmGetUser(m.uid)
|
||||
user, err := database.AmGetUser(ctx, m.uid)
|
||||
if err == nil {
|
||||
// Build the final headers.
|
||||
hdrs := make(map[string]string)
|
||||
@@ -177,7 +178,7 @@ func transmitMessage(m *amMessage, body []byte) {
|
||||
// senderLoop collects E-mail messages from the channel and pushes them out.
|
||||
func senderLoop(sent chan *amMessage, done chan bool) {
|
||||
for m := range sent {
|
||||
body, err := formatMessage(m)
|
||||
body, err := formatMessage(context.Background(), m)
|
||||
if err == nil {
|
||||
transmitMessage(m, body)
|
||||
} else {
|
||||
|
||||
@@ -38,7 +38,7 @@ func loadCategoryInformation(ctxt ui.AmContext, offset int) error {
|
||||
}
|
||||
}
|
||||
if catid > -1 {
|
||||
cat, err := database.AmGetCategory(catid) // this step also resolves symlinks
|
||||
cat, err := database.AmGetCategory(ctxt.Ctx(), catid) // this step also resolves symlinks
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -48,12 +48,12 @@ func loadCategoryInformation(ctxt ui.AmContext, offset int) error {
|
||||
ctxt.VarMap().Set("catid", catid)
|
||||
showHidden := database.AmTestPermission("Global.ShowHiddenCategories", u.BaseLevel)
|
||||
ctxt.VarMap().Set("showHiddenCat", showHidden)
|
||||
hier, err := database.AmGetCategoryHierarchy(catid)
|
||||
hier, err := database.AmGetCategoryHierarchy(ctxt.Ctx(), catid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctxt.VarMap().Set("catHierarchy", hier)
|
||||
subs, err := database.AmGetSubCategories(catid)
|
||||
subs, err := database.AmGetSubCategories(ctxt.Ctx(), catid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func loadCategoryInformation(ctxt ui.AmContext, offset int) error {
|
||||
if catid > -1 {
|
||||
// search for communities in this category
|
||||
listMax := int(ctxt.Globals().MaxSearchPage)
|
||||
commList, numComm, err := database.AmGetCommunitiesForCategory(catid, offset*listMax, listMax, showHidden)
|
||||
commList, numComm, err := database.AmGetCommunitiesForCategory(ctxt.Ctx(), catid, offset*listMax, listMax, showHidden)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -207,7 +207,7 @@ func Find(ctxt ui.AmContext) (string, any, error) {
|
||||
return "framed_template", "find.jet", nil
|
||||
}
|
||||
var clist []*database.Community
|
||||
clist, total, err = database.AmSearchCommunities(iField, iOper, term, ofs*listMax, listMax,
|
||||
clist, total, err = database.AmSearchCommunities(ctxt.Ctx(), iField, iOper, term, ofs*listMax, listMax,
|
||||
ctxt.TestPermission("Global.SearchHiddenCommunities"))
|
||||
if err == nil {
|
||||
if clist == nil {
|
||||
@@ -244,7 +244,7 @@ func Find(ctxt ui.AmContext) (string, any, error) {
|
||||
return "framed_template", "find.jet", nil
|
||||
}
|
||||
var ulist []*database.User
|
||||
ulist, total, err = database.AmSearchUsers(iField, iOper, term, ofs*listMax, listMax)
|
||||
ulist, total, err = database.AmSearchUsers(ctxt.Ctx(), iField, iOper, term, ofs*listMax, listMax)
|
||||
if err == nil {
|
||||
if ulist == nil {
|
||||
numResults = 0
|
||||
@@ -268,7 +268,7 @@ func Find(ctxt ui.AmContext) (string, any, error) {
|
||||
return "framed_template", "find.jet", nil
|
||||
}
|
||||
var catlist []*database.Category
|
||||
catlist, total, err = database.AmSearchCategories(iOper, term, ofs*listMax, listMax,
|
||||
catlist, total, err = database.AmSearchCategories(ctxt.Ctx(), iOper, term, ofs*listMax, listMax,
|
||||
ctxt.TestPermission("Global.ShowHiddenCategories"), ctxt.TestPermission("Global.SearchHiddenCategories"))
|
||||
if err == nil {
|
||||
if catlist == nil {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package htmlcheck
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -81,6 +82,7 @@ const hyphApos = "-'"
|
||||
|
||||
// htmlCheckerImpl is the implementation of the HTML checker.
|
||||
type htmlCheckerImpl struct {
|
||||
ctx context.Context // request context, as instances are generally per-request
|
||||
config *HTMLCheckerConfig // pointer to configuration
|
||||
started bool // has checker been started?
|
||||
finished bool // has checker been finished?
|
||||
@@ -147,13 +149,14 @@ func (ht *htmlCheckerImpl) copyOutputFilters(dest []outputFilter, source []strin
|
||||
*/
|
||||
|
||||
/* AmNewHTMLChecker creates a new HTML Checker object.
|
||||
* Parametrers:
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* configName - Name of the configuration to use.
|
||||
* Returns:
|
||||
* New HTML checker reference.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmNewHTMLChecker(configName string) (HTMLChecker, error) {
|
||||
func AmNewHTMLChecker(ctx context.Context, configName string) (HTMLChecker, error) {
|
||||
config, ok := configsRegistry[configName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("configuration %s not found", configName)
|
||||
@@ -166,6 +169,7 @@ func AmNewHTMLChecker(configName string) (HTMLChecker, error) {
|
||||
}
|
||||
}
|
||||
rc := htmlCheckerImpl{
|
||||
ctx: ctx,
|
||||
config: config,
|
||||
started: false,
|
||||
finished: false,
|
||||
@@ -486,7 +490,7 @@ func (ht *htmlCheckerImpl) emitFromStartOfTempBuffer(nrunes int) {
|
||||
// attemptRewrite attempts to apply a list of rewriters on the text, returning the first one that matches.
|
||||
func (ht *htmlCheckerImpl) attemptRewrite(rewriters []rewriter, data string) *markupData {
|
||||
for _, r := range rewriters {
|
||||
rc := r.Rewrite(data, ht)
|
||||
rc := r.Rewrite(ht.ctx, data, ht)
|
||||
if rc != nil {
|
||||
return rc
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package htmlcheck
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"os"
|
||||
|
||||
@@ -76,12 +77,13 @@ func (rw *spellingRewriter) Name() string {
|
||||
|
||||
/* Rewrite rewrites the given string data and adds markup before and after if needed.
|
||||
* Parameters:
|
||||
* ctx - Standard Go error status.
|
||||
* data - The data to be rewritten.
|
||||
* svc - Services interface we can use.
|
||||
* Returns:
|
||||
* Pointer to markup data, or nil.
|
||||
*/
|
||||
func (rw *spellingRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||
func (rw *spellingRewriter) Rewrite(ctx context.Context, data string, svc rewriterServices) *markupData {
|
||||
if rw.dict.CheckWord(data) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package htmlcheck
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"math"
|
||||
"regexp"
|
||||
@@ -90,12 +91,13 @@ func (rw *emoticonRewriter) Name() string {
|
||||
|
||||
/* Rewrite rewrites the given string data and adds markup before and after if needed.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* data - The data to be rewritten.
|
||||
* svc - Services interface we can use.
|
||||
* Returns:
|
||||
* Pointer to markup data, or nil.
|
||||
*/
|
||||
func (rw *emoticonRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||
func (rw *emoticonRewriter) Rewrite(ctx context.Context, data string, svc rewriterServices) *markupData {
|
||||
pos := math.MaxInt
|
||||
for _, c := range rw.prefixChars {
|
||||
foo := strings.IndexByte(data, c)
|
||||
@@ -163,12 +165,13 @@ func (rw *emoticonTagRewriter) Name() string {
|
||||
|
||||
/* Rewrite rewrites the given string data and adds markup before and after if needed.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* data - The data to be rewritten.
|
||||
* svc - Services interface we can use.
|
||||
* Returns:
|
||||
* Pointer to markup data, or nil.
|
||||
*/
|
||||
func (rw *emoticonTagRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||
func (rw *emoticonTagRewriter) Rewrite(ctx context.Context, data string, svc rewriterServices) *markupData {
|
||||
m := rw.re.FindStringSubmatch(data)
|
||||
if m == nil {
|
||||
return nil
|
||||
|
||||
+10
-8
@@ -10,6 +10,7 @@
|
||||
package htmlcheck
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"net/url"
|
||||
@@ -41,7 +42,7 @@ type rewriterServices interface {
|
||||
// rewriter is the interface for components that rewrite source text and place markup around it.
|
||||
type rewriter interface {
|
||||
Name() string
|
||||
Rewrite(string, rewriterServices) *markupData
|
||||
Rewrite(context.Context, string, rewriterServices) *markupData
|
||||
}
|
||||
|
||||
// rewriterRegistry contains a list of all rewriters.
|
||||
@@ -72,7 +73,7 @@ func (rw *emailRewriter) Name() string {
|
||||
* Returns:
|
||||
* Pointer to markup data, or nil.
|
||||
*/
|
||||
func (rw *emailRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||
func (rw *emailRewriter) Rewrite(ctx context.Context, data string, svc rewriterServices) *markupData {
|
||||
_, err := mail.ParseAddress(data)
|
||||
if err != nil {
|
||||
return nil
|
||||
@@ -154,7 +155,7 @@ func buildPostLink(decoded, context *database.PostLinkData) string {
|
||||
* Returns:
|
||||
* Pointer to markup data, or nil.
|
||||
*/
|
||||
func (rw *postLinkRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||
func (rw *postLinkRewriter) Rewrite(ctx context.Context, data string, svc rewriterServices) *markupData {
|
||||
q := svc.rewriterContextValue("PostLinkDecoderContext")
|
||||
if q == nil {
|
||||
return nil
|
||||
@@ -165,7 +166,7 @@ func (rw *postLinkRewriter) Rewrite(data string, svc rewriterServices) *markupDa
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
err = mydata.VerifyNames()
|
||||
err = mydata.VerifyNames(ctx)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -205,17 +206,18 @@ func (rw *userLinkRewriter) Name() string {
|
||||
|
||||
/* Rewrite rewrites the given string data and adds markup before and after if needed.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* data - The data to be rewritten.
|
||||
* svc - Services interface we can use.
|
||||
* Returns:
|
||||
* Pointer to markup data, or nil.
|
||||
*/
|
||||
func (rw *userLinkRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||
func (rw *userLinkRewriter) Rewrite(ctx context.Context, data string, svc rewriterServices) *markupData {
|
||||
if data == "" || len(data) > 64 || !database.AmIsValidAmsterdamID(data) {
|
||||
return nil
|
||||
}
|
||||
|
||||
user, err := database.AmGetUserByName(data, nil)
|
||||
user, err := database.AmGetUserByName(ctx, data, nil)
|
||||
if err != nil || user == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -258,8 +260,8 @@ func (rw *countingRewriter) Name() string {
|
||||
* Returns:
|
||||
* Pointer to markup data, or nil.
|
||||
*/
|
||||
func (rw *countingRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||
rc := rw.inner.Rewrite(data, svc)
|
||||
func (rw *countingRewriter) Rewrite(ctx context.Context, data string, svc rewriterServices) *markupData {
|
||||
rc := rw.inner.Rewrite(ctx, data, svc)
|
||||
if rc != nil && !rc.rescan {
|
||||
rw.count++
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package htmlcheck
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -72,12 +73,13 @@ func (rw *urlRewriter) Name() string {
|
||||
|
||||
/* Rewrite rewrites the given string data and adds markup before and after if needed.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* data - The data to be rewritten.
|
||||
* svc - Services interface we can use.
|
||||
* Returns:
|
||||
* Pointer to markup data, or nil.
|
||||
*/
|
||||
func (rw *urlRewriter) Rewrite(data string, svc rewriterServices) *markupData {
|
||||
func (rw *urlRewriter) Rewrite(ctx context.Context, data string, svc rewriterServices) *markupData {
|
||||
for _, ue := range urlElements {
|
||||
s := ue.eval(data)
|
||||
if s != "" {
|
||||
|
||||
@@ -80,10 +80,10 @@ func Login(ctxt ui.AmContext) (string, any, error) {
|
||||
return dlg.RenderError(ctxt, "User name not specified.")
|
||||
}
|
||||
if action == "remind" { // Password Reminder button pressed
|
||||
user, uerr := database.AmGetUserByName(username, nil)
|
||||
user, uerr := database.AmGetUserByName(ctxt.Ctx(), username, nil)
|
||||
if uerr == nil {
|
||||
var ci *database.ContactInfo
|
||||
ci, uerr = user.ContactInfo()
|
||||
ci, uerr = user.ContactInfo(ctxt.Ctx())
|
||||
if uerr == nil {
|
||||
if ci != nil && ci.Email != nil && *ci.Email != "" {
|
||||
pchange := database.AmNewPasswordChangeRequest(user.Uid, user.Username, *ci.Email)
|
||||
@@ -109,14 +109,14 @@ func Login(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
if action == "login" { // Login button pressed
|
||||
// authenticate the user
|
||||
user, uerr := database.AmAuthenticateUser(username, dlg.Field("pass").Value, ctxt.RemoteIP())
|
||||
user, uerr := database.AmAuthenticateUser(ctxt.Ctx(), username, dlg.Field("pass").Value, ctxt.RemoteIP())
|
||||
if uerr != nil {
|
||||
return dlg.RenderError(ctxt, uerr.Error())
|
||||
}
|
||||
ctxt.ReplaceUser(user)
|
||||
if dlg.Field("saveme").IsChecked() {
|
||||
// create and save an authentication token
|
||||
authString, cerr := user.NewAuthToken()
|
||||
authString, cerr := user.NewAuthToken(ctxt.Ctx())
|
||||
if cerr == nil {
|
||||
ctxt.SetLoginCookie(authString)
|
||||
|
||||
@@ -240,9 +240,9 @@ func VerifyEMail(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
if action == "sendagain" {
|
||||
var ci *database.ContactInfo
|
||||
ci, err = user.ContactInfo()
|
||||
ci, err = user.ContactInfo(ctxt.Ctx())
|
||||
if err == nil {
|
||||
err = user.NewEmailConfirmationNumber()
|
||||
err = user.NewEmailConfirmationNumber(ctxt.Ctx())
|
||||
if err == nil {
|
||||
err = sendEmailConfirmationEmail(user, ci, ctxt.RemoteIP())
|
||||
}
|
||||
@@ -257,7 +257,7 @@ func VerifyEMail(ctxt ui.AmContext) (string, any, error) {
|
||||
err = dlg.Validate()
|
||||
if err == nil {
|
||||
cn, _ := dlg.Field("num").ValueInt()
|
||||
err = user.ConfirmEMailAddress(int32(cn), ctxt.RemoteIP())
|
||||
err = user.ConfirmEMailAddress(ctxt.Ctx(), int32(cn), ctxt.RemoteIP())
|
||||
if err == nil {
|
||||
return "redirect", target, nil
|
||||
}
|
||||
@@ -358,14 +358,14 @@ func NewAccount(ctxt ui.AmContext) (string, any, error) {
|
||||
return dlg.RenderError(ctxt, "The typed passwords do not match.")
|
||||
}
|
||||
var banned bool
|
||||
banned, err = database.AmIsEmailAddressBanned(dlg.Field("email").Value)
|
||||
banned, err = database.AmIsEmailAddressBanned(ctxt.Ctx(), dlg.Field("email").Value)
|
||||
if err == nil {
|
||||
if banned {
|
||||
return dlg.RenderError(ctxt, "This E-mail address may not register a new account.")
|
||||
}
|
||||
// Create new user account
|
||||
var user *database.User
|
||||
user, err = database.AmCreateNewUser(dlg.Field("user").Value, dlg.Field("pass1").Value,
|
||||
user, err = database.AmCreateNewUser(ctxt.Ctx(), dlg.Field("user").Value, dlg.Field("pass1").Value,
|
||||
dlg.Field("remind").Value, dlg.Field("dob").AsDate(), ctxt.RemoteIP())
|
||||
if err == nil {
|
||||
// create and save contact info
|
||||
@@ -384,9 +384,9 @@ func NewAccount(ctxt ui.AmContext) (string, any, error) {
|
||||
ci.PostalCode = dlg.Field("pcode").ValPtr()
|
||||
ci.Country = dlg.Field("country").ValPtr()
|
||||
ci.Email = dlg.Field("email").ValPtr()
|
||||
_, err = ci.Save()
|
||||
_, err = ci.Save(ctxt.Ctx())
|
||||
if err == nil {
|
||||
err = user.SetContactID(ci.ContactId)
|
||||
err = user.SetContactID(ctxt.Ctx(), ci.ContactId)
|
||||
}
|
||||
if err == nil {
|
||||
err = sendEmailConfirmationEmail(user, ci, ctxt.RemoteIP())
|
||||
@@ -435,10 +435,10 @@ func PasswordRecovery(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
user, err := database.AmGetUser(int32(uid))
|
||||
user, err := database.AmGetUser(ctxt.Ctx(), int32(uid))
|
||||
if err == nil {
|
||||
newpass := util.GenerateRandomPassword()
|
||||
err = user.ChangePassword(newpass, ctxt.RemoteIP())
|
||||
err = user.ChangePassword(ctxt.Ctx(), newpass, ctxt.RemoteIP())
|
||||
if err == nil {
|
||||
// send the password change message
|
||||
msg := email.AmNewEmailMessage(user.Uid, ctxt.RemoteIP())
|
||||
|
||||
@@ -124,9 +124,6 @@ func main() {
|
||||
closer = ui.SetupAmContext()
|
||||
defer closer()
|
||||
|
||||
// Set up Echo.
|
||||
e := setupEcho()
|
||||
|
||||
// Set up to trap SIGINT and shut down gracefully
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer stop()
|
||||
@@ -138,6 +135,9 @@ func main() {
|
||||
ampool.Shutdown()
|
||||
}()
|
||||
|
||||
// Set up Echo.
|
||||
e := setupEcho()
|
||||
|
||||
// Start server
|
||||
go func() {
|
||||
if err := e.Start(":1323"); err != nil && err != http.ErrServerClosed {
|
||||
|
||||
@@ -48,11 +48,11 @@ type RenderedSidebox struct {
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func buildCommunitiesSidebox(uid int32, out *RenderedSidebox, in *database.Sidebox) error {
|
||||
user, err := database.AmGetUser(uid)
|
||||
func buildCommunitiesSidebox(ctxt ui.AmContext, uid int32, out *RenderedSidebox, in *database.Sidebox) error {
|
||||
user, err := database.AmGetUser(ctxt.Ctx(), uid)
|
||||
if err == nil {
|
||||
var g *database.Globals
|
||||
g, err = database.AmGlobals()
|
||||
g, err = database.AmGlobals(ctxt.Ctx())
|
||||
if err == nil {
|
||||
if user.IsAnon {
|
||||
out.Title = "Featured Communities"
|
||||
@@ -60,7 +60,7 @@ func buildCommunitiesSidebox(uid int32, out *RenderedSidebox, in *database.Sideb
|
||||
out.Title = "Your Communities"
|
||||
}
|
||||
var l []*database.Community
|
||||
l, err = database.AmGetCommunitiesForUser(uid)
|
||||
l, err = database.AmGetCommunitiesForUser(ctxt.Ctx(), uid)
|
||||
if err == nil {
|
||||
out.Items = make([]RenderedSideboxItem, len(l))
|
||||
for i, c := range l {
|
||||
@@ -69,7 +69,7 @@ func buildCommunitiesSidebox(uid int32, out *RenderedSidebox, in *database.Sideb
|
||||
out.Items[i].Link = &lk
|
||||
out.Items[i].Flags = make(map[string]bool)
|
||||
var level uint16
|
||||
level, err = database.AmGetCommunityAccessLevel(uid, c.Id)
|
||||
level, err = database.AmGetCommunityAccessLevel(ctxt.Ctx(), uid, c.Id)
|
||||
if err == nil && database.AmTestPermission("Community.ShowAdmin", level) {
|
||||
out.Items[i].Flags["admin"] = true
|
||||
}
|
||||
@@ -150,10 +150,10 @@ func buildUsersOnline(uid int32, out *RenderedSidebox, in *database.Sidebox) err
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func buildRenderedSidebox(uid int32, out *RenderedSidebox, in *database.Sidebox) error {
|
||||
func buildRenderedSidebox(ctxt ui.AmContext, uid int32, out *RenderedSidebox, in *database.Sidebox) error {
|
||||
switch in.Boxid {
|
||||
case 1:
|
||||
return buildCommunitiesSidebox(uid, out, in)
|
||||
return buildCommunitiesSidebox(ctxt, uid, out, in)
|
||||
case 2:
|
||||
return buildFeaturedConferences(uid, out, in)
|
||||
case 3:
|
||||
@@ -177,14 +177,14 @@ func TopPage(ctxt ui.AmContext) (string, any, error) {
|
||||
|
||||
// Retrieve the sideboxes and create the data to be presented.
|
||||
uid := ctxt.CurrentUserId()
|
||||
sboxes, err := database.AmGetSideboxes(uid)
|
||||
sboxes, err := database.AmGetSideboxes(ctxt.Ctx(), uid)
|
||||
if err != nil {
|
||||
return "string", "Unable to retrieve sideboxes", err
|
||||
}
|
||||
|
||||
rc := make([]RenderedSidebox, len(sboxes))
|
||||
for i, sb := range sboxes {
|
||||
err = buildRenderedSidebox(uid, &(rc[i]), sb)
|
||||
err = buildRenderedSidebox(ctxt, uid, &(rc[i]), sb)
|
||||
if err != nil {
|
||||
return "string", "Unable to render sideboxes", err
|
||||
}
|
||||
|
||||
+8
-8
@@ -120,7 +120,7 @@ func (c *amContext) ClearLoginCookie() {
|
||||
|
||||
// ClearSession clears the current session.
|
||||
func (c *amContext) ClearSession() {
|
||||
AmResetSession(c.session)
|
||||
AmResetSession(c.echoContext.Request().Context(), c.session)
|
||||
c.user = nil
|
||||
c.effectiveLevel = 0
|
||||
}
|
||||
@@ -144,7 +144,7 @@ func (c *amContext) CurrentCommunity() *database.Community {
|
||||
// CurrentUser returns the current user from the session.
|
||||
func (c *amContext) CurrentUser() *database.User {
|
||||
if c.user == nil {
|
||||
u, err := database.AmGetUser(AmSessionUid(c.session))
|
||||
u, err := database.AmGetUser(c.echoContext.Request().Context(), AmSessionUid(c.session))
|
||||
if err != nil {
|
||||
log.Errorf("unable to retrieve current user")
|
||||
}
|
||||
@@ -327,12 +327,12 @@ func (c *amContext) SubRender(name string) ([]byte, error) {
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (c *amContext) SetCommunityContext(param string) error {
|
||||
comm, err := database.AmGetCommunityFromParam(param)
|
||||
comm, err := database.AmGetCommunityFromParam(c.echoContext.Request().Context(), param)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.community == nil || c.community.Id != comm.Id {
|
||||
mbr, lock, level, err := comm.Membership(c.CurrentUser())
|
||||
mbr, lock, level, err := comm.Membership(c.echoContext.Request().Context(), c.CurrentUser())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -459,11 +459,11 @@ func newContext(ctxt echo.Context) (*amContext, error) {
|
||||
}
|
||||
|
||||
var err error
|
||||
if rc.globals, err = database.AmGlobals(); err != nil {
|
||||
if rc.globals, err = database.AmGlobals(ctxt.Request().Context()); err != nil {
|
||||
amContextRecycleBin <- rc
|
||||
return nil, err
|
||||
}
|
||||
if rc.globalFlags, err = rc.globals.Flags(); err != nil {
|
||||
if rc.globalFlags, err = rc.globals.Flags(ctxt.Request().Context()); err != nil {
|
||||
amContextRecycleBin <- rc
|
||||
return nil, err
|
||||
}
|
||||
@@ -475,12 +475,12 @@ func newContext(ctxt echo.Context) (*amContext, error) {
|
||||
rc.session = sess
|
||||
sess.Options = defoptions
|
||||
if sess.IsNew {
|
||||
AmSessionFirstTime(sess)
|
||||
AmSessionFirstTime(ctxt.Request().Context(), sess)
|
||||
} else {
|
||||
AmHitSession(sess)
|
||||
}
|
||||
}
|
||||
rc.user, err = database.AmGetUser(AmSessionUid(sess))
|
||||
rc.user, err = database.AmGetUser(ctxt.Request().Context(), AmSessionUid(sess))
|
||||
if err == nil {
|
||||
rc.effectiveLevel = rc.user.BaseLevel
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ func AmServeImage(ctxt AmContext) (string, any, error) {
|
||||
id, err = strconv.Atoi(components[3])
|
||||
if err == nil {
|
||||
var img *database.ImageStore
|
||||
img, err = database.AmLoadImage(int32(id))
|
||||
img, err = database.AmLoadImage(ctxt.Ctx(), int32(id))
|
||||
if err == nil {
|
||||
ctxt.SetOutputType(img.MimeType)
|
||||
return "bytes", img.Data, nil
|
||||
|
||||
+4
-2
@@ -10,6 +10,7 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"slices"
|
||||
@@ -141,19 +142,20 @@ func AmMenu(name string) *MenuDefinition {
|
||||
|
||||
/* AmBuildCommunityMenu buids a community menu for the specified community.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
* comm - The community to build the menu for.
|
||||
* Returns:
|
||||
* The new menu definition.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmBuildCommunityMenu(comm *database.Community) (*MenuDefinition, error) {
|
||||
func AmBuildCommunityMenu(ctx context.Context, comm *database.Community) (*MenuDefinition, error) {
|
||||
menuCacheMutex.Lock()
|
||||
defer menuCacheMutex.Unlock()
|
||||
m, ok := menuCache.Get(comm.Id)
|
||||
if ok {
|
||||
return m.(*MenuDefinition), nil
|
||||
}
|
||||
sdef, err := database.AmGetCommunityServices(comm.Id)
|
||||
sdef, err := database.AmGetCommunityServices(ctx, comm.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+6
-6
@@ -31,7 +31,7 @@ func middlewareErrorPage(c echo.Context, ctxt AmContext, err error) error {
|
||||
func IPBanTest(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
// Check IP banning.
|
||||
banmsg, banerr := database.AmTestIPBan(c.RealIP())
|
||||
banmsg, banerr := database.AmTestIPBan(c.Request().Context(), c.RealIP())
|
||||
if banerr != nil {
|
||||
c.Logger().Warnf("address %s could not be tested: %v", c.RealIP(), banerr)
|
||||
// but let the request pass anyway
|
||||
@@ -55,12 +55,12 @@ func CookieLoginTest(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
cookie, err := c.Cookie(config.GlobalConfig.Site.LoginCookieName)
|
||||
if err == nil {
|
||||
var user *database.User
|
||||
user, err = database.AmAuthenticateUserByToken(cookie.Value, c.RealIP())
|
||||
user, err = database.AmAuthenticateUserByToken(c.Request().Context(), cookie.Value, c.RealIP())
|
||||
if err == nil {
|
||||
// log the user in and rotate login cookie
|
||||
amctxt.ReplaceUser(user)
|
||||
var newToken string
|
||||
if newToken, err = user.NewAuthToken(); err == nil {
|
||||
if newToken, err = user.NewAuthToken(c.Request().Context()); err == nil {
|
||||
amctxt.SetLoginCookie(newToken)
|
||||
} else {
|
||||
log.Warnf("unable to rotate login cookie: %v", err)
|
||||
@@ -99,7 +99,7 @@ func ValidateConference(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
ctxt := AmContextFromEchoContext(c)
|
||||
comm := ctxt.CurrentCommunity() // set by middleware
|
||||
b, err := database.AmTestService(comm, "Conference")
|
||||
b, err := database.AmTestService(c.Request().Context(), comm, "Conference")
|
||||
if err != nil {
|
||||
return middlewareErrorPage(c, ctxt, err)
|
||||
}
|
||||
@@ -122,11 +122,11 @@ func ValidateConference(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
func SetConference(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
ctxt := AmContextFromEchoContext(c)
|
||||
conf, err := database.AmGetConferenceByAliasInCommunity(ctxt.CurrentCommunity().Id, ctxt.URLParam("confid"))
|
||||
conf, err := database.AmGetConferenceByAliasInCommunity(ctxt.Ctx(), ctxt.CurrentCommunity().Id, ctxt.URLParam("confid"))
|
||||
if err != nil {
|
||||
return middlewareErrorPage(c, ctxt, err)
|
||||
}
|
||||
m, lvl, err := conf.Membership(ctxt.CurrentUser())
|
||||
m, lvl, err := conf.Membership(ctxt.Ctx(), ctxt.CurrentUser())
|
||||
if err != nil {
|
||||
return middlewareErrorPage(c, ctxt, err)
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ func AmSendPageData(ctxt echo.Context, amctxt AmContext, command string, data an
|
||||
case "top":
|
||||
menus[0] = AmMenu("top")
|
||||
case "community":
|
||||
md, err := AmBuildCommunityMenu(amctxt.CurrentCommunity())
|
||||
md, err := AmBuildCommunityMenu(ctxt.Request().Context(), amctxt.CurrentCommunity())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+7
-6
@@ -11,6 +11,7 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/gob"
|
||||
"encoding/hex"
|
||||
@@ -220,8 +221,8 @@ func AmSetSessionUser(session *sessions.Session, user *database.User) {
|
||||
}
|
||||
|
||||
// setSessionAnon sets the user for the session to the anonymous user.
|
||||
func setSessionAnon(session *sessions.Session) {
|
||||
u, err := database.AmGetAnonUser()
|
||||
func setSessionAnon(ctx context.Context, session *sessions.Session) {
|
||||
u, err := database.AmGetAnonUser(ctx)
|
||||
if err == nil {
|
||||
AmSetSessionUser(session, u)
|
||||
} else {
|
||||
@@ -232,20 +233,20 @@ func setSessionAnon(session *sessions.Session) {
|
||||
var lastHitMutex sync.Mutex
|
||||
|
||||
// AmSessionFirstTime initializes the session after it's first created.
|
||||
func AmSessionFirstTime(session *sessions.Session) {
|
||||
func AmSessionFirstTime(ctx context.Context, session *sessions.Session) {
|
||||
lastHitMutex.Lock()
|
||||
setSessionAnon(session)
|
||||
setSessionAnon(ctx, session)
|
||||
session.Values["lasthit"] = time.Now()
|
||||
lastHitMutex.Unlock()
|
||||
}
|
||||
|
||||
// AmResetSession clears the specified session.
|
||||
func AmResetSession(session *sessions.Session) {
|
||||
func AmResetSession(ctx context.Context, session *sessions.Session) {
|
||||
lastHitMutex.Lock()
|
||||
for k := range session.Values {
|
||||
delete(session.Values, k)
|
||||
}
|
||||
setSessionAnon(session)
|
||||
setSessionAnon(ctx, session)
|
||||
session.Values["lasthit"] = time.Now()
|
||||
lastHitMutex.Unlock()
|
||||
}
|
||||
|
||||
+8
-6
@@ -112,7 +112,8 @@ func immediateIf(a jet.Arguments) reflect.Value {
|
||||
func extractCommunityLogo(a jet.Arguments) reflect.Value {
|
||||
rc := "/img/builtin/default-community.jpg"
|
||||
comm := a.Get(0).Convert(reflect.TypeFor[*database.Community]()).Interface().(*database.Community)
|
||||
ci, err := comm.ContactInfo()
|
||||
ctxt := a.Get(1).Convert(reflect.TypeFor[AmContext]()).Interface().(AmContext)
|
||||
ci, err := comm.ContactInfo(ctxt.Ctx())
|
||||
if err == nil {
|
||||
if ci.PhotoURL != nil && *ci.PhotoURL != "" {
|
||||
rc = *ci.PhotoURL
|
||||
@@ -125,7 +126,7 @@ func extractCommunityLogo(a jet.Arguments) reflect.Value {
|
||||
func displayDateTime(a jet.Arguments) reflect.Value {
|
||||
timeval := a.Get(0).Convert(reflect.TypeFor[time.Time]()).Interface().(time.Time)
|
||||
ctxt := a.Get(1).Convert(reflect.TypeFor[AmContext]()).Interface().(AmContext)
|
||||
prefs, err := ctxt.CurrentUser().Prefs()
|
||||
prefs, err := ctxt.CurrentUser().Prefs(ctxt.Ctx())
|
||||
if err == nil {
|
||||
loc := prefs.Localizer()
|
||||
return reflect.ValueOf(loc.Strftime("%b %e, %Y %r", timeval))
|
||||
@@ -137,7 +138,7 @@ func displayDateTime(a jet.Arguments) reflect.Value {
|
||||
func displayActivity(a jet.Arguments) reflect.Value {
|
||||
timeval := a.Get(0).Convert(reflect.TypeFor[*time.Time]()).Interface().(*time.Time)
|
||||
ctxt := a.Get(1).Convert(reflect.TypeFor[AmContext]()).Interface().(AmContext)
|
||||
prefs, err := ctxt.CurrentUser().Prefs()
|
||||
prefs, err := ctxt.CurrentUser().Prefs(ctxt.Ctx())
|
||||
if err == nil {
|
||||
return reflect.ValueOf(util.AmActivityString(timeval, prefs.Localizer()))
|
||||
}
|
||||
@@ -150,14 +151,14 @@ func displayMemberCount(a jet.Arguments) reflect.Value {
|
||||
comm := a.Get(0).Convert(reflect.TypeFor[*database.Community]()).Interface().(*database.Community)
|
||||
ctxt := a.Get(1).Convert(reflect.TypeFor[AmContext]()).Interface().(AmContext)
|
||||
level := ctxt.CurrentUser().BaseLevel
|
||||
mbr, _, clevel, err := comm.Membership(ctxt.CurrentUser())
|
||||
mbr, _, clevel, err := comm.Membership(ctxt.Ctx(), ctxt.CurrentUser())
|
||||
if err == nil {
|
||||
if mbr && clevel > level {
|
||||
level = clevel
|
||||
}
|
||||
showHidden = comm.TestPermission("Community.ShowHiddenMembers", level)
|
||||
}
|
||||
count, err := comm.MemberCount(showHidden)
|
||||
count, err := comm.MemberCount(ctxt.Ctx(), showHidden)
|
||||
if err != nil {
|
||||
return reflect.ValueOf(-1)
|
||||
}
|
||||
@@ -194,7 +195,8 @@ func displayFullName(a jet.Arguments) reflect.Value {
|
||||
// displayExpandCat displays a category expanded into a hierarchy.
|
||||
func displayExpandCat(a jet.Arguments) reflect.Value {
|
||||
cat := a.Get(0).Convert(reflect.TypeFor[*database.Category]()).Interface().(*database.Category)
|
||||
hier, _ := database.AmGetCategoryHierarchy(cat.CatId)
|
||||
ctxt := a.Get(1).Convert(reflect.TypeFor[AmContext]()).Interface().(AmContext)
|
||||
hier, _ := database.AmGetCategoryHierarchy(ctxt.Ctx(), cat.CatId)
|
||||
var rc strings.Builder
|
||||
for i, c := range hier {
|
||||
if i > 0 {
|
||||
|
||||
+1
-1
@@ -257,7 +257,7 @@
|
||||
<span class="text-sm pt-0.5 flex-shrink-0">🟣</span>
|
||||
<div class="flex-1 mb-2">
|
||||
<a href="/find?mode=COM&catid={{ rx.CatId }}"
|
||||
class="text-blue-700 hover:text-blue-900 font-bold text-base">{{ DisplayExpandCat(rx) }}</a>
|
||||
class="text-blue-700 hover:text-blue-900 font-bold text-base">{{ DisplayExpandCat(rx, .) }}</a>
|
||||
</div>
|
||||
</div>
|
||||
{{ else if mode == "PST" }}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{{ comm := .CurrentCommunity() }}
|
||||
<div class="mb-2 mt-2">
|
||||
<div class="mb-1">
|
||||
<img src="{{ ExtractCommunityLogo(comm) }}" alt="{{ comm.Name }}" class="w-28 h-16 rounded">
|
||||
<img src="{{ ExtractCommunityLogo(comm, .) }}" alt="{{ comm.Name }}" class="w-28 h-16 rounded">
|
||||
</div>
|
||||
<div class="font-bold mb-1">{{ menu.Title }}</div>
|
||||
{{ ctxt := . }}
|
||||
|
||||
+2
-2
@@ -79,8 +79,8 @@
|
||||
{{ post_overrideLine := "" }}
|
||||
{{ post_overrideLink := "" }}
|
||||
{{ range i, post_cur := posts }}
|
||||
{{ post_userName = post_getUserName(post_cur) }}
|
||||
{{ post_text = post_getText(post_cur) }}
|
||||
{{ post_userName = post_getUserName(post_cur, .) }}
|
||||
{{ post_text = post_getText(post_cur, .) }}
|
||||
{{ post_overrideLine = post_getOverrideLine(post_cur, .) }}
|
||||
{{ post_overrideLink = post_getOverrideLink(post_cur, post_topicPermalink) }}
|
||||
{{ .SubRender("singlepost.jet") | raw }}
|
||||
|
||||
+24
-24
@@ -57,10 +57,10 @@ func EditProfileForm(ctxt ui.AmContext) (string, any, error) {
|
||||
dlg.Field("tgt").Value = target
|
||||
ctxt.VarMap().Set("target", target)
|
||||
var ci *database.ContactInfo
|
||||
ci, err = u.ContactInfo()
|
||||
ci, err = u.ContactInfo(ctxt.Ctx())
|
||||
if err == nil {
|
||||
var prefs *database.UserPrefs
|
||||
prefs, err = u.Prefs()
|
||||
prefs, err = u.Prefs(ctxt.Ctx())
|
||||
if err == nil {
|
||||
dlg.Field("remind").Value = u.PassReminder
|
||||
dlg.Field("prefix").SetVal(ci.Prefix)
|
||||
@@ -87,8 +87,8 @@ func EditProfileForm(ctxt ui.AmContext) (string, any, error) {
|
||||
dlg.Field("dob").SetDate(u.DOB)
|
||||
dlg.Field("descr").SetVal(u.Description)
|
||||
dlg.Field("photo").Value = userPhotoURL(ci)
|
||||
dlg.Field("pic_in_post").SetChecked(u.FlagValue(database.UserFlagPicturesInPosts))
|
||||
dlg.Field("no_mass_mail").SetChecked(u.FlagValue(database.UserFlagMassMailOptOut))
|
||||
dlg.Field("pic_in_post").SetChecked(u.FlagValue(ctxt.Ctx(), database.UserFlagPicturesInPosts))
|
||||
dlg.Field("no_mass_mail").SetChecked(u.FlagValue(ctxt.Ctx(), database.UserFlagMassMailOptOut))
|
||||
dlg.Field("locale").Value = prefs.ReadLocale()
|
||||
dlg.Field("tz").Value = prefs.TimeZoneID
|
||||
return dlg.Render(ctxt)
|
||||
@@ -130,15 +130,15 @@ func EditProfile(ctxt ui.AmContext) (string, any, error) {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
var ci *database.ContactInfo
|
||||
ci, err = u.ContactInfo()
|
||||
ci, err = u.ContactInfo(ctxt.Ctx())
|
||||
if err == nil {
|
||||
var prefs *database.UserPrefs
|
||||
emailChange := false
|
||||
prefs, err = u.Prefs()
|
||||
prefs, err = u.Prefs(ctxt.Ctx())
|
||||
if err == nil && !(dlg.Field("pass1").IsEmpty() && dlg.Field("pass2").IsEmpty()) {
|
||||
p1 := dlg.Field("pass1").Value
|
||||
if p1 == dlg.Field("pass2").Value {
|
||||
err = u.ChangePassword(p1, ctxt.RemoteIP())
|
||||
err = u.ChangePassword(ctxt.Ctx(), p1, ctxt.RemoteIP())
|
||||
} else {
|
||||
err = errors.New("passwords do not match")
|
||||
}
|
||||
@@ -166,27 +166,27 @@ func EditProfile(ctxt ui.AmContext) (string, any, error) {
|
||||
nci.Email = dlg.Field("email").ValPtr()
|
||||
nci.PrivateEmail = dlg.Field("pvt_email").IsChecked()
|
||||
nci.URL = dlg.Field("url").ValPtr()
|
||||
emailChange, err = nci.Save()
|
||||
emailChange, err = nci.Save(ctxt.Ctx())
|
||||
ci = nci
|
||||
}
|
||||
if err == nil {
|
||||
nprefs := prefs.Clone()
|
||||
nprefs.WriteLocale(dlg.Field("locale").Value)
|
||||
nprefs.TimeZoneID = dlg.Field("tz").Value
|
||||
err = nprefs.Save(u)
|
||||
err = nprefs.Save(ctxt.Ctx(), u)
|
||||
}
|
||||
if err == nil {
|
||||
var f *util.OptionSet
|
||||
f, err = u.Flags()
|
||||
f, err = u.Flags(ctxt.Ctx())
|
||||
if err == nil {
|
||||
nf := f.Clone()
|
||||
nf.Set(database.UserFlagPicturesInPosts, dlg.Field("pic_in_post").IsChecked())
|
||||
nf.Set(database.UserFlagMassMailOptOut, dlg.Field("no_mass_mail").IsChecked())
|
||||
err = u.SaveFlags(nf)
|
||||
err = u.SaveFlags(ctxt.Ctx(), nf)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
err = u.SetProfileData(dlg.Field("remind").Value, dlg.Field("dob").AsDate(), dlg.Field("descr").ValPtr())
|
||||
err = u.SetProfileData(ctxt.Ctx(), dlg.Field("remind").Value, dlg.Field("dob").AsDate(), dlg.Field("descr").ValPtr())
|
||||
}
|
||||
if err == nil {
|
||||
if emailChange {
|
||||
@@ -223,7 +223,7 @@ func ProfilePhotoForm(ctxt ui.AmContext) (string, any, error) {
|
||||
if u.IsAnon {
|
||||
return ui.ErrorPage(ctxt, errors.New("you are not logged in"))
|
||||
}
|
||||
ci, err := u.ContactInfo()
|
||||
ci, err := u.ContactInfo(ctxt.Ctx())
|
||||
if err == nil {
|
||||
ctxt.VarMap().Set("target", target)
|
||||
ctxt.VarMap().Set("photo_url", userPhotoURL(ci))
|
||||
@@ -247,7 +247,7 @@ func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
|
||||
if u.IsAnon {
|
||||
return ui.ErrorPage(ctxt, errors.New("you are not logged in"))
|
||||
}
|
||||
ci, err := u.ContactInfo()
|
||||
ci, err := u.ContactInfo(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -267,11 +267,11 @@ func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
|
||||
ui.UserPhotoMaxBytes)
|
||||
if err == nil {
|
||||
var img *database.ImageStore
|
||||
img, err = database.AmStoreImage(database.ImageTypeUserPhoto, u.Uid, mimeType, imageData)
|
||||
img, err = database.AmStoreImage(ctxt.Ctx(), database.ImageTypeUserPhoto, u.Uid, mimeType, imageData)
|
||||
if err == nil {
|
||||
photourl := fmt.Sprintf("/img/store/%d", img.ImgId)
|
||||
ci.PhotoURL = &photourl
|
||||
_, err = ci.Save()
|
||||
_, err = ci.Save(ctxt.Ctx())
|
||||
if err == nil {
|
||||
return "redirect", "/profile?tgt=" + url.QueryEscape(target), nil
|
||||
}
|
||||
@@ -300,7 +300,7 @@ func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
|
||||
defer func() {
|
||||
if happy {
|
||||
ampool.Submit(func(context.Context) {
|
||||
err := database.AmDeleteImage(int32(id))
|
||||
err := database.AmDeleteImage(ctxt.Ctx(), int32(id))
|
||||
if err != nil {
|
||||
log.Errorf("unable to delete image ID %d: %v", id, err)
|
||||
}
|
||||
@@ -309,7 +309,7 @@ func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
|
||||
}()
|
||||
}
|
||||
ci.PhotoURL = nil
|
||||
_, err := ci.Save()
|
||||
_, err := ci.Save(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -329,18 +329,18 @@ func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
|
||||
*/
|
||||
func ShowProfile(ctxt ui.AmContext) (string, any, error) {
|
||||
me := ctxt.CurrentUser()
|
||||
prefs, err := me.Prefs()
|
||||
prefs, err := me.Prefs(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
|
||||
// Gather the info on the current user.
|
||||
user, err := database.AmGetUserByName(ctxt.URLParam("uname"), nil)
|
||||
user, err := database.AmGetUserByName(ctxt.Ctx(), ctxt.URLParam("uname"), nil)
|
||||
if err != nil {
|
||||
ctxt.SetRC(http.StatusNotFound)
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
ci, err := user.ContactInfo()
|
||||
ci, err := user.ContactInfo(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -449,7 +449,7 @@ func QuickEMail(ctxt ui.AmContext) (string, any, error) {
|
||||
if me.IsAnon {
|
||||
return ui.ErrorPage(ctxt, errors.New("you are not logged in"))
|
||||
}
|
||||
myCI, err := me.ContactInfo()
|
||||
myCI, err := me.ContactInfo(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
@@ -457,14 +457,14 @@ func QuickEMail(ctxt ui.AmContext) (string, any, error) {
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
user, err := database.AmGetUser(int32(toUid))
|
||||
user, err := database.AmGetUser(ctxt.Ctx(), int32(toUid))
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
if user.IsAnon {
|
||||
return ui.ErrorPage(ctxt, errors.New("cannot send quick E-mail to anonymous user"))
|
||||
}
|
||||
ci, err := user.ContactInfo()
|
||||
ci, err := user.ContactInfo(ctxt.Ctx())
|
||||
if err != nil {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user