completed manage conference list
This commit is contained in:
@@ -865,3 +865,39 @@ func ManageConferenceList(ctxt ui.AmContext) (string, any) {
|
||||
ctxt.SetFrameTitle("Manage Conference List")
|
||||
return "framed", "manage_conflist.jet"
|
||||
}
|
||||
|
||||
/* ManageDeleteConference handles the deletion of a conference from the management menu.
|
||||
* Parameters:
|
||||
* ctxt - The AmContext for the request.
|
||||
* Returns:
|
||||
* Command string dictating what to be rendered.
|
||||
* Data as a parameter for the command string.
|
||||
*/
|
||||
func ManageDeleteConference(ctxt ui.AmContext) (string, any) {
|
||||
comm := ctxt.CurrentCommunity()
|
||||
conf := ctxt.GetScratch("currentConference").(*database.Conference)
|
||||
myLevel := ctxt.GetScratch("levelInConference").(uint16)
|
||||
if !conf.TestPermission("Conference.Delete", myLevel) {
|
||||
return "error", ENOPERM
|
||||
}
|
||||
|
||||
// Load the message box, and, if we have a valid "yes," then perform the delete
|
||||
mbox, err := ui.AmLoadMessageBox("deleteConf")
|
||||
if err != nil {
|
||||
return "error", err
|
||||
}
|
||||
if mbox.Validate(ctxt, "yes") {
|
||||
err := conf.Delete(ctxt.Ctx(), comm, ctxt.CurrentUser(), ctxt.RemoteIP(), ampool)
|
||||
if err != nil {
|
||||
return "error", err
|
||||
}
|
||||
return "redirect", fmt.Sprintf("/comm/%s/manage_conf", ctxt.CurrentCommunity().Alias)
|
||||
}
|
||||
|
||||
// Set up to display the message box.
|
||||
mbox.SetMessage(fmt.Sprintf(`You are about to delete the conference <span class="font-bold text-red-600">"%s"</span>
|
||||
from the <span class="font-bold text-red-600">"%s"</span> community!`, conf.Name, comm.Name))
|
||||
mbox.SetLink("no", fmt.Sprintf("/comm/%s/manage_conf", ctxt.CurrentCommunity().Alias))
|
||||
mbox.SetLink("yes", fmt.Sprintf("/comm/%s/manage_conf/del/%s", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias")))
|
||||
return mbox.Render(ctxt)
|
||||
}
|
||||
|
||||
@@ -813,6 +813,131 @@ func (c *Conference) Stats(ctx context.Context) (int, int, error) {
|
||||
return ntopic, npost, err
|
||||
}
|
||||
|
||||
// backgroundPurgeConference purges out all the conference information in the background.
|
||||
func backgroundPurgeConference(ctx context.Context, confid int32) error {
|
||||
// Purge out auxiliary conference tables first.
|
||||
tx := amdb.MustBegin()
|
||||
_, err := tx.ExecContext(ctx, "DELETE FROM confmember WHERE confid = ?", confid)
|
||||
if err != nil {
|
||||
log.Warnf("backgroundPurgeConference(%d): failed purging confmember: %v", confid, err)
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM confsettings WHERE confid = ?", confid)
|
||||
if err != nil {
|
||||
log.Warnf("backgroundPurgeConference(%d): failed purging confsettings: %v", confid, err)
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM confhotlist WHERE confid = ?", confid)
|
||||
if err != nil {
|
||||
log.Warnf("backgroundPurgeConference(%d): failed purging confhotlist: %v", confid, err)
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM propconf WHERE confid = ?", confid)
|
||||
if err != nil {
|
||||
log.Warnf("backgroundPurgeConference(%d): failed purging propconf: %v", confid, err)
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM confcustom WHERE confid = ?", confid)
|
||||
if err != nil {
|
||||
log.Warnf("backgroundPurgeConference(%d): failed purging confcustom: %v", confid, err)
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
// Get all topic IDs in this conference.
|
||||
var topicIds []int32
|
||||
err = amdb.SelectContext(ctx, &topicIds, "SELECT topicid FROM topics WHERE confid = ?", confid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Erase each topic in turn by calling two of the "delete topic" internal functions.
|
||||
for _, topicId := range topicIds {
|
||||
tx := amdb.MustBegin()
|
||||
err = eraseTopicRecords(ctx, tx, topicId)
|
||||
if err == nil {
|
||||
err = tx.Commit()
|
||||
}
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
err = backgroundPurgeTopic(ctx, topicId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete unlinks this conference from the community, deleting it entirely if the last link is gone.
|
||||
func (c *Conference) Delete(ctx context.Context, comm *Community, u *User, ipaddr string, background *util.WorkerPool) error {
|
||||
success := false
|
||||
tx := amdb.MustBegin()
|
||||
defer func() {
|
||||
if !success {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
getConferenceMutex.Lock()
|
||||
defer getConferenceMutex.Unlock()
|
||||
|
||||
// any references to conference other than this community?
|
||||
row := tx.QueryRowContext(ctx, "SELECT COUNT(*) FROM commtoconf WHERE confid = ? AND commid <> ?", c.ConfId, comm.Id)
|
||||
refCount := 0
|
||||
err := row.Scan(&refCount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// break the link with the community
|
||||
if _, err = tx.ExecContext(ctx, "DELETE FROM commtoconf WHERE commid = ? AND confid = ?", comm.Id, c.ConfId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if refCount == 0 {
|
||||
// We have to delete all the conference core data now.
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM confs WHERE confid = ?", c.ConfId)
|
||||
if err == nil {
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM confalias WHERE confid = ?", c.ConfId)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = tx.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
success = true
|
||||
|
||||
if refCount == 0 {
|
||||
// kick the conference out of the cache
|
||||
conferenceCache.Remove(c.ConfId)
|
||||
|
||||
// add an audit record
|
||||
AmStoreAudit(AmNewAudit(AuditConferenceDelete, u.Uid, ipaddr, fmt.Sprintf("confid=%d", c.ConfId)))
|
||||
|
||||
// set up a background job to purge the rest of the data
|
||||
confid := c.ConfId
|
||||
background.Submit(func(ctx context.Context) {
|
||||
start := time.Now()
|
||||
// Just dump the whole conference property cache
|
||||
getConferencePropMutex.Lock()
|
||||
conferencePropCache.Purge()
|
||||
getConferencePropMutex.Unlock()
|
||||
|
||||
// purge the conference data
|
||||
err := backgroundPurgeConference(ctx, confid)
|
||||
if err != nil {
|
||||
log.Errorf("Conference purge(#%d) background job failed: %v", confid, err)
|
||||
}
|
||||
dur := time.Since(start)
|
||||
log.Infof("Conference.Delete task completed in %v", dur)
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* AmGetConference returns a conference given its ID.
|
||||
* Parameters:
|
||||
* ctx - Standard Go context value.
|
||||
|
||||
@@ -478,10 +478,13 @@ func (t *Topic) Delete(ctx context.Context, u *User, ipaddr string, background *
|
||||
// Spin off a background task to finish deleting this topic.
|
||||
myTopicId := t.TopicId
|
||||
background.Submit(func(ctx context.Context) {
|
||||
start := time.Now()
|
||||
err := backgroundPurgeTopic(ctx, myTopicId)
|
||||
if err != nil {
|
||||
log.Errorf("backgroundTopicPurge FAILED with %v", err)
|
||||
}
|
||||
dur := time.Since(start)
|
||||
log.Infof("Topic.Delete task completed in %v", dur)
|
||||
})
|
||||
|
||||
return nil
|
||||
|
||||
+5
-2
@@ -126,10 +126,13 @@ func (m *amMessage) Send() {
|
||||
* The new Message.
|
||||
*/
|
||||
func AmNewEmailMessage(sender int32, ip string) Message {
|
||||
rc := freeMessages.Get().(*amMessage)
|
||||
if rc == nil {
|
||||
var rc *amMessage
|
||||
tmp := freeMessages.Get()
|
||||
if tmp == nil {
|
||||
rc = &amMessage{to: make([]string, 0), cc: make([]string, 0), bcc: make([]string, 0),
|
||||
headers: make(map[string]string), vars: make(jet.VarMap)}
|
||||
} else {
|
||||
rc = tmp.(*amMessage)
|
||||
}
|
||||
rc.uid = sender
|
||||
rc.ip = ip
|
||||
|
||||
@@ -118,8 +118,10 @@ func setupEcho() *echo.Echo {
|
||||
// conference group
|
||||
commGroup.GET("/create_conf", ui.AmWrap(CreateConferenceForm))
|
||||
commGroup.POST("/create_conf", ui.AmWrap(CreateConference))
|
||||
commGroup.GET("/manage_conf", ui.AmWrap(ManageConferenceList))
|
||||
commGroup.GET("/manage_conf", ui.AmWrap(ManageConferenceList), ui.ValidateConference)
|
||||
commGroup.GET("/manage_conf/del/:confid", ui.AmWrap(ManageDeleteConference), ui.ValidateConference, ui.SetConference)
|
||||
commGroup.GET("/conf", ui.AmWrap(Conferences), ui.ValidateConference)
|
||||
|
||||
confGroup := commGroup.Group("/conf/:confid", ui.ValidateConference, ui.SetConference)
|
||||
confGroup.GET("", ui.AmWrap(Topics))
|
||||
confGroup.GET("/new_topic", ui.AmWrap(NewTopicForm))
|
||||
@@ -145,6 +147,7 @@ func setupEcho() *echo.Echo {
|
||||
confGroup.GET("/invite", ui.AmWrap(InviteToConference))
|
||||
confGroup.GET("/r/:topic", ui.AmWrap(ReadPosts), ui.SetTopic)
|
||||
confGroup.POST("/r/:topic", ui.AmWrap(PostInTopic), ui.SetTopic)
|
||||
|
||||
opsGroup := confGroup.Group("/op/:topic", ui.SetTopic)
|
||||
opsGroup.GET("/find", ui.AmWrap(FindPostsPageTopic))
|
||||
opsGroup.POST("/find", ui.AmWrap(FindPostsTopic))
|
||||
|
||||
+5
-2
@@ -524,14 +524,17 @@ var amContextRecycleBin chan *amContext
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func newContext(ctxt echo.Context) (*amContext, error) {
|
||||
rc := freeContext.Get().(*amContext)
|
||||
if rc == nil {
|
||||
var rc *amContext
|
||||
tmp := freeContext.Get()
|
||||
if tmp == nil {
|
||||
rc = &amContext{
|
||||
rendervars: make(jet.VarMap),
|
||||
frameTitle: "",
|
||||
frameMeta: make(map[int]map[string]string),
|
||||
outputType: "",
|
||||
}
|
||||
} else {
|
||||
rc = tmp.(*amContext)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
@@ -55,3 +55,29 @@ messagedefs:
|
||||
tone: "green"
|
||||
icon: "✗"
|
||||
text: "No, Cancel"
|
||||
- id: "deleteConf"
|
||||
title: "Delete Conference"
|
||||
tone: "red"
|
||||
destructive: true
|
||||
message: "You are about to delete a conference!"
|
||||
warningIcon: "💣"
|
||||
warningLines:
|
||||
- text: "Warning: This action cannot be undone!"
|
||||
bold: true
|
||||
- text: "Deleting this conference will permanently remove it and all its topics from the system."
|
||||
bold: false
|
||||
- text: "Hundreds or even thousands of conference posts will be lost forever."
|
||||
bold: false
|
||||
buttons:
|
||||
- id: "yes"
|
||||
link: "placeholder"
|
||||
confirm: true
|
||||
tone: "red"
|
||||
icon: "✓"
|
||||
text: "Yes, Delete It"
|
||||
- id: "no"
|
||||
link: "placeholder"
|
||||
confirm: false
|
||||
tone: "green"
|
||||
icon: "✗"
|
||||
text: "No, Cancel"
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
{{ end }}
|
||||
</td>
|
||||
<td class="px-4 py-3 whitespace-nowrap text-center w-12">
|
||||
<a href="/TODO" class="text-2xl hover:scale-125 inline-block transition-transform"
|
||||
<a href="{{ baseUrl }}/del/{{ c.Alias }}" class="text-2xl hover:scale-125 inline-block transition-transform"
|
||||
title="Delete Conference">❌</a>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm">
|
||||
|
||||
Reference in New Issue
Block a user