refactor mod stuff
This commit is contained in:
parent
e8fa40c0ca
commit
e87d739392
@ -8,7 +8,7 @@ import (
|
|||||||
type CacheInterface interface {
|
type CacheInterface interface {
|
||||||
RegenAll()
|
RegenAll()
|
||||||
RegenFrontPage()
|
RegenFrontPage()
|
||||||
RegenOnModEvent(string, string, string, int)
|
RegenOnModEvent(newsgroup, msgid, root string, page int)
|
||||||
RegenerateBoard(group string)
|
RegenerateBoard(group string)
|
||||||
Regen(msg ArticleEntry)
|
Regen(msg ArticleEntry)
|
||||||
|
|
||||||
|
@ -535,28 +535,6 @@ func (self *NNTPDaemon) Run() {
|
|||||||
self.allow_anon_attachments = self.conf.daemon["allow_anon_attachments"] == "1"
|
self.allow_anon_attachments = self.conf.daemon["allow_anon_attachments"] == "1"
|
||||||
self.allow_attachments = self.conf.daemon["allow_attachments"] == "1"
|
self.allow_attachments = self.conf.daemon["allow_attachments"] == "1"
|
||||||
|
|
||||||
// do we enable the frontend?
|
|
||||||
if self.conf.frontend["enable"] == "1" {
|
|
||||||
log.Printf("frontend %s enabled", self.conf.frontend["name"])
|
|
||||||
|
|
||||||
cache_host := self.conf.cache["host"]
|
|
||||||
cache_port := self.conf.cache["port"]
|
|
||||||
cache_user := self.conf.cache["user"]
|
|
||||||
cache_passwd := self.conf.cache["password"]
|
|
||||||
self.cache = NewCache(self.conf.cache["type"], cache_host, cache_port, cache_user, cache_passwd, self.conf.cache, self.conf.frontend, self.database, self.store)
|
|
||||||
|
|
||||||
script, ok := self.conf.frontend["markup_script"]
|
|
||||||
if ok {
|
|
||||||
err = SetMarkupScriptFile(script)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("failed to load markup script", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.frontend = NewHTTPFrontend(self, self.cache, self.conf.frontend, self.conf.worker["url"])
|
|
||||||
go self.frontend.Mainloop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up admin user if it's specified in the config
|
// set up admin user if it's specified in the config
|
||||||
pubkey, ok := self.conf.frontend["admin_key"]
|
pubkey, ok := self.conf.frontend["admin_key"]
|
||||||
if ok {
|
if ok {
|
||||||
@ -572,6 +550,9 @@ func (self *NNTPDaemon) Run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start frontend
|
||||||
|
go self.frontend.Mainloop()
|
||||||
|
|
||||||
log.Println("we have", len(self.conf.feeds), "feeds")
|
log.Println("we have", len(self.conf.feeds), "feeds")
|
||||||
|
|
||||||
defer self.listener.Close()
|
defer self.listener.Close()
|
||||||
@ -647,7 +628,6 @@ func (self *NNTPDaemon) Run() {
|
|||||||
log.Println("started worker", threads)
|
log.Println("started worker", threads)
|
||||||
threads--
|
threads--
|
||||||
}
|
}
|
||||||
|
|
||||||
// start accepting incoming connections
|
// start accepting incoming connections
|
||||||
self.acceptloop()
|
self.acceptloop()
|
||||||
<-self.done
|
<-self.done
|
||||||
@ -838,7 +818,6 @@ func (self *NNTPDaemon) pump_article_requests() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *NNTPDaemon) poll(worker int) {
|
func (self *NNTPDaemon) poll(worker int) {
|
||||||
modchnl := self.mod.MessageChan()
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case msgid := <-self.infeed_load:
|
case msgid := <-self.infeed_load:
|
||||||
@ -863,7 +842,7 @@ func (self *NNTPDaemon) poll(worker int) {
|
|||||||
}
|
}
|
||||||
// send to mod panel
|
// send to mod panel
|
||||||
if group == "ctl" {
|
if group == "ctl" {
|
||||||
modchnl <- msgid
|
self.mod.HandleMessage(msgid)
|
||||||
}
|
}
|
||||||
// inform callback hooks
|
// inform callback hooks
|
||||||
self.informHooks(group, msgid, ref)
|
self.informHooks(group, msgid, ref)
|
||||||
@ -1081,11 +1060,36 @@ func (self *NNTPDaemon) Setup() {
|
|||||||
log.Println("set up article store...")
|
log.Println("set up article store...")
|
||||||
self.store = createArticleStore(self.conf.store, self.database)
|
self.store = createArticleStore(self.conf.store, self.database)
|
||||||
|
|
||||||
self.mod = modEngine{
|
// do we enable the frontend?
|
||||||
|
if self.conf.frontend["enable"] == "1" {
|
||||||
|
log.Printf("frontend %s enabled", self.conf.frontend["name"])
|
||||||
|
|
||||||
|
cache_host := self.conf.cache["host"]
|
||||||
|
cache_port := self.conf.cache["port"]
|
||||||
|
cache_user := self.conf.cache["user"]
|
||||||
|
cache_passwd := self.conf.cache["password"]
|
||||||
|
self.cache = NewCache(self.conf.cache["type"], cache_host, cache_port, cache_user, cache_passwd, self.conf.cache, self.conf.frontend, self.database, self.store)
|
||||||
|
|
||||||
|
script, ok := self.conf.frontend["markup_script"]
|
||||||
|
if ok {
|
||||||
|
err = SetMarkupScriptFile(script)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("failed to load markup script", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.frontend = NewHTTPFrontend(self, self.cache, self.conf.frontend, self.conf.worker["url"])
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mod = &modEngine{
|
||||||
store: self.store,
|
store: self.store,
|
||||||
database: self.database,
|
database: self.database,
|
||||||
chnl: make(chan string),
|
regen: self.frontend.RegenOnModEvent,
|
||||||
}
|
}
|
||||||
// inject DB into template engine
|
// inject DB into template engine
|
||||||
template.DB = self.database
|
template.DB = self.database
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (daemon *NNTPDaemon) ModEngine() ModEngine {
|
||||||
|
return daemon.mod
|
||||||
|
}
|
||||||
|
@ -63,7 +63,6 @@ func (self expire) ExpirePost(messageID string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self expire) ExpireGroup(newsgroup string, keep int) {
|
func (self expire) ExpireGroup(newsgroup string, keep int) {
|
||||||
log.Println("Expire group", newsgroup, keep)
|
|
||||||
threads := self.database.GetRootPostsForExpiration(newsgroup, keep)
|
threads := self.database.GetRootPostsForExpiration(newsgroup, keep)
|
||||||
for _, root := range threads {
|
for _, root := range threads {
|
||||||
self.ExpireThread(newsgroup, root)
|
self.ExpireThread(newsgroup, root)
|
||||||
@ -127,7 +126,6 @@ func (self expire) ExpireOrphans() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self expire) handleEvent(ev deleteEvent) {
|
func (self expire) handleEvent(ev deleteEvent) {
|
||||||
log.Println("expire", ev.MessageID())
|
|
||||||
atts := self.database.GetPostAttachments(ev.MessageID())
|
atts := self.database.GetPostAttachments(ev.MessageID())
|
||||||
// remove all attachments
|
// remove all attachments
|
||||||
if atts != nil {
|
if atts != nil {
|
||||||
@ -147,5 +145,5 @@ func (self expire) handleEvent(ev deleteEvent) {
|
|||||||
log.Println("failed to delete article", err)
|
log.Println("failed to delete article", err)
|
||||||
}
|
}
|
||||||
// remove article
|
// remove article
|
||||||
os.Remove(ev.Path())
|
self.store.Remove(ev.MessageID())
|
||||||
}
|
}
|
||||||
|
@ -36,4 +36,6 @@ type Frontend interface {
|
|||||||
|
|
||||||
// trigger a manual regen of indexes for a root post
|
// trigger a manual regen of indexes for a root post
|
||||||
Regen(msg ArticleEntry)
|
Regen(msg ArticleEntry)
|
||||||
|
// regenerate on mod event
|
||||||
|
RegenOnModEvent(newsgroup, msgid, root string, page int)
|
||||||
}
|
}
|
||||||
|
@ -1483,7 +1483,7 @@ func (self *httpFrontend) Mainloop() {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
// run daemon's mod engine with our frontend
|
// run daemon's mod engine with our frontend
|
||||||
go RunModEngine(self.daemon.mod, self.cache.RegenOnModEvent)
|
// go RunModEngine(self.daemon.mod, self.cache.RegenOnModEvent)
|
||||||
|
|
||||||
// start cache
|
// start cache
|
||||||
self.cache.Start()
|
self.cache.Start()
|
||||||
@ -1517,6 +1517,10 @@ func (self *httpFrontend) endLiveUI() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *httpFrontend) RegenOnModEvent(newsgroup, msgid, root string, page int) {
|
||||||
|
self.cache.RegenOnModEvent(newsgroup, msgid, root, page)
|
||||||
|
}
|
||||||
|
|
||||||
// create a new http based frontend
|
// create a new http based frontend
|
||||||
func NewHTTPFrontend(daemon *NNTPDaemon, cache CacheInterface, config map[string]string, url string) Frontend {
|
func NewHTTPFrontend(daemon *NNTPDaemon, cache CacheInterface, config map[string]string, url string) Frontend {
|
||||||
template.Minimize = config["minimize_html"] == "1"
|
template.Minimize = config["minimize_html"] == "1"
|
||||||
|
@ -46,6 +46,12 @@ func (self multiFrontend) PostsChan() chan frontendPost {
|
|||||||
return self.muxedpostchan
|
return self.muxedpostchan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self multiFrontend) RegenOnModEvent(newsgroup, msgid, root string, page int) {
|
||||||
|
for idx := range self.frontends {
|
||||||
|
self.frontends[idx].RegenOnModEvent(newsgroup, msgid, root, page)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func MuxFrontends(fronts ...Frontend) Frontend {
|
func MuxFrontends(fronts ...Frontend) Frontend {
|
||||||
var front multiFrontend
|
var front multiFrontend
|
||||||
front.muxedpostchan = make(chan frontendPost, 64)
|
front.muxedpostchan = make(chan frontendPost, 64)
|
||||||
|
@ -23,14 +23,9 @@ type AdminFunc func(param map[string]interface{}) (interface{}, error)
|
|||||||
|
|
||||||
// interface for moderation ui
|
// interface for moderation ui
|
||||||
type ModUI interface {
|
type ModUI interface {
|
||||||
|
|
||||||
// channel for daemon to poll for nntp articles from the mod ui
|
|
||||||
MessageChan() chan NNTPMessage
|
|
||||||
|
|
||||||
// check if this key is allowed to access
|
// check if this key is allowed to access
|
||||||
// return true if it can otherwise false
|
// return true if it can otherwise false
|
||||||
CheckKey(privkey, scope string) (bool, error)
|
CheckKey(privkey, scope string) (bool, error)
|
||||||
|
|
||||||
// serve the base page
|
// serve the base page
|
||||||
ServeModPage(wr http.ResponseWriter, r *http.Request)
|
ServeModPage(wr http.ResponseWriter, r *http.Request)
|
||||||
// handle a login POST request
|
// handle a login POST request
|
||||||
@ -49,6 +44,8 @@ type ModUI interface {
|
|||||||
HandleKeyGen(wr http.ResponseWriter, r *http.Request)
|
HandleKeyGen(wr http.ResponseWriter, r *http.Request)
|
||||||
// handle admin command
|
// handle admin command
|
||||||
HandleAdminCommand(wr http.ResponseWriter, r *http.Request)
|
HandleAdminCommand(wr http.ResponseWriter, r *http.Request)
|
||||||
|
// get outbound message channel
|
||||||
|
MessageChan() chan NNTPMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModEvent interface {
|
type ModEvent interface {
|
||||||
@ -149,10 +146,10 @@ func wrapModMessage(mm ModMessage) NNTPMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ModEngine interface {
|
type ModEngine interface {
|
||||||
// chan to send the mod engine posts given message_id
|
// load and handle a mod message from ctl after it's verified
|
||||||
MessageChan() chan string
|
HandleMessage(msgid string)
|
||||||
// delete post of a poster
|
// delete post of a poster
|
||||||
DeletePost(msgid string, regen RegenFunc) error
|
DeletePost(msgid string) error
|
||||||
// ban a cidr
|
// ban a cidr
|
||||||
BanAddress(cidr string) error
|
BanAddress(cidr string) error
|
||||||
// do we allow this public key to delete this message-id ?
|
// do we allow this public key to delete this message-id ?
|
||||||
@ -161,28 +158,28 @@ type ModEngine interface {
|
|||||||
AllowBan(pubkey string) bool
|
AllowBan(pubkey string) bool
|
||||||
// load a mod message
|
// load a mod message
|
||||||
LoadMessage(msgid string) NNTPMessage
|
LoadMessage(msgid string) NNTPMessage
|
||||||
|
// execute 1 mod action line by a mod with pubkey
|
||||||
|
Execute(ev ModEvent, pubkey string)
|
||||||
|
// do a mod event unconditionally
|
||||||
|
Do(ev ModEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
type modEngine struct {
|
type modEngine struct {
|
||||||
database Database
|
database Database
|
||||||
store ArticleStore
|
store ArticleStore
|
||||||
chnl chan string
|
regen RegenFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self modEngine) LoadMessage(msgid string) NNTPMessage {
|
func (self *modEngine) LoadMessage(msgid string) NNTPMessage {
|
||||||
return self.store.GetMessage(msgid)
|
return self.store.GetMessage(msgid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self modEngine) MessageChan() chan string {
|
func (self *modEngine) BanAddress(cidr string) (err error) {
|
||||||
return self.chnl
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self modEngine) BanAddress(cidr string) (err error) {
|
|
||||||
return self.database.BanAddr(cidr)
|
return self.database.BanAddr(cidr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self modEngine) DeletePost(msgid string, regen RegenFunc) (err error) {
|
func (self *modEngine) DeletePost(msgid string) (err error) {
|
||||||
hdr, err := self.database.GetHeadersForMessage(msgid)
|
hdr := self.store.GetHeaders(msgid)
|
||||||
var delposts []string
|
var delposts []string
|
||||||
var page int64
|
var page int64
|
||||||
var ref, group string
|
var ref, group string
|
||||||
@ -231,10 +228,6 @@ func (self modEngine) DeletePost(msgid string, regen RegenFunc) (err error) {
|
|||||||
os.Remove(f)
|
os.Remove(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rootmsgid != "" {
|
|
||||||
self.database.DeleteThread(rootmsgid)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, delmsg := range delposts {
|
for _, delmsg := range delposts {
|
||||||
// delete article from post database
|
// delete article from post database
|
||||||
err = self.database.DeleteArticle(delmsg)
|
err = self.database.DeleteArticle(delmsg)
|
||||||
@ -243,12 +236,17 @@ func (self modEngine) DeletePost(msgid string, regen RegenFunc) (err error) {
|
|||||||
}
|
}
|
||||||
// ban article
|
// ban article
|
||||||
self.database.BanArticle(delmsg, "deleted by moderator")
|
self.database.BanArticle(delmsg, "deleted by moderator")
|
||||||
|
self.store.Remove(delmsg)
|
||||||
}
|
}
|
||||||
regen(group, msgid, ref, int(page))
|
|
||||||
|
if rootmsgid != "" {
|
||||||
|
self.database.DeleteThread(rootmsgid)
|
||||||
|
}
|
||||||
|
self.regen(group, msgid, ref, int(page))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self modEngine) AllowBan(pubkey string) bool {
|
func (self *modEngine) AllowBan(pubkey string) bool {
|
||||||
is_admin, _ := self.database.CheckAdminPubkey(pubkey)
|
is_admin, _ := self.database.CheckAdminPubkey(pubkey)
|
||||||
if is_admin {
|
if is_admin {
|
||||||
// admins can do whatever
|
// admins can do whatever
|
||||||
@ -257,7 +255,7 @@ func (self modEngine) AllowBan(pubkey string) bool {
|
|||||||
return self.database.CheckModPubkeyGlobal(pubkey)
|
return self.database.CheckModPubkeyGlobal(pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self modEngine) AllowDelete(pubkey, msgid string) (allow bool) {
|
func (self *modEngine) AllowDelete(pubkey, msgid string) (allow bool) {
|
||||||
is_admin, _ := self.database.CheckAdminPubkey(pubkey)
|
is_admin, _ := self.database.CheckAdminPubkey(pubkey)
|
||||||
if is_admin {
|
if is_admin {
|
||||||
// admins can do whatever
|
// admins can do whatever
|
||||||
@ -277,88 +275,166 @@ func (self modEngine) AllowDelete(pubkey, msgid string) (allow bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// run a mod engine logic mainloop
|
func (mod *modEngine) HandleMessage(msgid string) {
|
||||||
func RunModEngine(mod ModEngine, regen RegenFunc) {
|
nntp := mod.store.GetMessage(msgid)
|
||||||
|
if nntp == nil {
|
||||||
chnl := mod.MessageChan()
|
log.Println("failed to load", msgid, "in mod engine, missing message")
|
||||||
for {
|
return
|
||||||
msgid := <-chnl
|
}
|
||||||
nntp := mod.LoadMessage(msgid)
|
// sanity check
|
||||||
if nntp == nil {
|
if nntp.Newsgroup() == "ctl" {
|
||||||
log.Println("failed to load mod message", msgid)
|
pubkey := nntp.Pubkey()
|
||||||
continue
|
for _, line := range strings.Split(nntp.Message(), "\n") {
|
||||||
}
|
line = strings.Trim(line, "\r\t\n ")
|
||||||
// sanity check
|
ev := ParseModEvent(line)
|
||||||
if nntp.Newsgroup() == "ctl" {
|
mod.Execute(ev, pubkey)
|
||||||
pubkey := nntp.Pubkey()
|
|
||||||
for _, line := range strings.Split(nntp.Message(), "\n") {
|
|
||||||
line = strings.Trim(line, "\r\t\n ")
|
|
||||||
ev := ParseModEvent(line)
|
|
||||||
action := ev.Action()
|
|
||||||
if action == "delete" {
|
|
||||||
msgid := ev.Target()
|
|
||||||
if !ValidMessageID(msgid) {
|
|
||||||
// invalid message-id
|
|
||||||
log.Println("invalid message-id for mod delete", msgid, "from", pubkey)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// this is a delete action
|
|
||||||
if mod.AllowDelete(pubkey, msgid) {
|
|
||||||
err := mod.DeletePost(msgid, regen)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(msgid, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("pubkey=%s will not delete %s not trusted", pubkey, msgid)
|
|
||||||
}
|
|
||||||
} else if action == "overchan-inet-ban" {
|
|
||||||
// ban action
|
|
||||||
target := ev.Target()
|
|
||||||
if target[0] == '[' {
|
|
||||||
// probably a literal ipv6 rangeban
|
|
||||||
if mod.AllowBan(pubkey) {
|
|
||||||
err := mod.BanAddress(target)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("failed to do literal ipv6 range ban on", target, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Println("ignoring literal ipv6 rangeban from", pubkey, "as they are not allowed to ban")
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
parts := strings.Split(target, ":")
|
|
||||||
if len(parts) == 3 {
|
|
||||||
// encrypted ip
|
|
||||||
encaddr, key := parts[0], parts[1]
|
|
||||||
cidr := decAddr(encaddr, key)
|
|
||||||
if cidr == "" {
|
|
||||||
log.Println("failed to decrypt inet ban")
|
|
||||||
} else if mod.AllowBan(pubkey) {
|
|
||||||
err := mod.BanAddress(cidr)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("failed to do range ban on", cidr, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Println("ingoring encrypted-ip inet ban from", pubkey, "as they are not allowed to ban")
|
|
||||||
}
|
|
||||||
} else if len(parts) == 1 {
|
|
||||||
// literal cidr
|
|
||||||
cidr := parts[0]
|
|
||||||
if mod.AllowBan(pubkey) {
|
|
||||||
err := mod.BanAddress(cidr)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("failed to do literal range ban on", cidr, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Println("ingoring literal cidr range ban from", pubkey, "as they are not allowed to ban")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("invalid overchan-inet-ban: target=%s", target)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Println("invalid mod action", action, "from", pubkey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mod *modEngine) Do(ev ModEvent) {
|
||||||
|
action := ev.Action()
|
||||||
|
if action == "delete" {
|
||||||
|
msgid := ev.Target()
|
||||||
|
if !ValidMessageID(msgid) {
|
||||||
|
// invalid message-id
|
||||||
|
log.Println("invalid message-id", msgid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := mod.DeletePost(msgid)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(msgid, err)
|
||||||
|
} else {
|
||||||
|
log.Println("deleted", msgid)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if action == "overchan-inet-ban" {
|
||||||
|
// ban action
|
||||||
|
target := ev.Target()
|
||||||
|
if target[0] == '[' {
|
||||||
|
err := mod.BanAddress(target)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("failed to do literal ipv6 range ban on", target, err)
|
||||||
|
} else {
|
||||||
|
log.Println("banned", target)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
parts := strings.Split(target, ":")
|
||||||
|
if len(parts) == 3 {
|
||||||
|
// encrypted ip
|
||||||
|
encaddr, key := parts[0], parts[1]
|
||||||
|
cidr := decAddr(encaddr, key)
|
||||||
|
if cidr == "" {
|
||||||
|
log.Println("failed to decrypt inet ban")
|
||||||
|
} else {
|
||||||
|
err := mod.BanAddress(cidr)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("failed to do range ban on", cidr, err)
|
||||||
|
} else {
|
||||||
|
log.Println("banned", cidr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if len(parts) == 2 {
|
||||||
|
// x-encrypted-ip ban without pad
|
||||||
|
err := mod.database.BanEncAddr(parts[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Println("failed to ban encrypted ip", err)
|
||||||
|
} else {
|
||||||
|
log.Println("banned poster", parts[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if len(parts) == 1 {
|
||||||
|
// literal cidr
|
||||||
|
cidr := parts[0]
|
||||||
|
err := mod.BanAddress(cidr)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("failed to do literal range ban on", cidr, err)
|
||||||
|
} else {
|
||||||
|
log.Println("banned cidr", cidr)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.Printf("invalid overchan-inet-ban: target=%s", target)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Println("invalid mod action", action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mod *modEngine) Execute(ev ModEvent, pubkey string) {
|
||||||
|
action := ev.Action()
|
||||||
|
if action == "delete" {
|
||||||
|
msgid := ev.Target()
|
||||||
|
if !ValidMessageID(msgid) {
|
||||||
|
// invalid message-id
|
||||||
|
log.Println("invalid message-id for mod delete from", pubkey)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// this is a delete action
|
||||||
|
if mod.AllowDelete(pubkey, msgid) {
|
||||||
|
err := mod.DeletePost(msgid)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(msgid, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("pubkey=%s will not delete %s not trusted", pubkey, msgid)
|
||||||
|
}
|
||||||
|
} else if action == "overchan-inet-ban" {
|
||||||
|
// ban action
|
||||||
|
target := ev.Target()
|
||||||
|
if target[0] == '[' {
|
||||||
|
// probably a literal ipv6 rangeban
|
||||||
|
if mod.AllowBan(pubkey) {
|
||||||
|
err := mod.BanAddress(target)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("failed to do literal ipv6 range ban on", target, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Println("ignoring literal ipv6 rangeban from", pubkey, "as they are not allowed to ban")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
parts := strings.Split(target, ":")
|
||||||
|
if len(parts) == 3 {
|
||||||
|
// encrypted ip
|
||||||
|
encaddr, key := parts[0], parts[1]
|
||||||
|
cidr := decAddr(encaddr, key)
|
||||||
|
if cidr == "" {
|
||||||
|
log.Println("failed to decrypt inet ban")
|
||||||
|
} else if mod.AllowBan(pubkey) {
|
||||||
|
err := mod.BanAddress(cidr)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("failed to do range ban on", cidr, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Println("ingoring encrypted-ip inet ban from", pubkey, "as they are not allowed to ban")
|
||||||
|
}
|
||||||
|
} else if len(parts) == 2 {
|
||||||
|
// x-encrypted-ip ban without pad
|
||||||
|
if mod.AllowBan(pubkey) {
|
||||||
|
err := mod.database.BanEncAddr(parts[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Println("failed to ban encrypted ip", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Println("ignoring encrypted-ip ban from", pubkey, "as they are not allowed to ban")
|
||||||
|
}
|
||||||
|
} else if len(parts) == 1 {
|
||||||
|
// literal cidr
|
||||||
|
cidr := parts[0]
|
||||||
|
if mod.AllowBan(pubkey) {
|
||||||
|
err := mod.BanAddress(cidr)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("failed to do literal range ban on", cidr, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Println("ingoring literal cidr range ban from", pubkey, "as they are not allowed to ban")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("invalid overchan-inet-ban: target=%s", target)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Println("invalid mod action", action, "from", pubkey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -70,6 +70,9 @@ type ArticleStore interface {
|
|||||||
|
|
||||||
// get thumbnail info of file by path
|
// get thumbnail info of file by path
|
||||||
ThumbInfo(fpath string) (ThumbInfo, error)
|
ThumbInfo(fpath string) (ThumbInfo, error)
|
||||||
|
|
||||||
|
// delete message by message-id
|
||||||
|
Remove(msgid string) error
|
||||||
}
|
}
|
||||||
type articleStore struct {
|
type articleStore struct {
|
||||||
directory string
|
directory string
|
||||||
@ -140,6 +143,16 @@ func (self *articleStore) Init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *articleStore) Remove(msgid string) (err error) {
|
||||||
|
if ValidMessageID(msgid) {
|
||||||
|
fpath := self.GetFilename(msgid)
|
||||||
|
err = os.Remove(fpath)
|
||||||
|
} else {
|
||||||
|
err = errors.New("invalid message-id: " + msgid)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (self *articleStore) RegisterSigned(msgid, pk string) (err error) {
|
func (self *articleStore) RegisterSigned(msgid, pk string) (err error) {
|
||||||
err = self.database.RegisterSigned(msgid, pk)
|
err = self.database.RegisterSigned(msgid, pk)
|
||||||
return
|
return
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -44,7 +45,32 @@ func main() {
|
|||||||
if len(os.Args) > 2 {
|
if len(os.Args) > 2 {
|
||||||
tool := os.Args[2]
|
tool := os.Args[2]
|
||||||
if tool == "mod" {
|
if tool == "mod" {
|
||||||
if len(os.Args) >= 5 {
|
if len(os.Args) == 4 && os.Args[3] == "do" {
|
||||||
|
daemon.Setup()
|
||||||
|
eng := daemon.ModEngine()
|
||||||
|
r := bufio.NewReader(os.Stdin)
|
||||||
|
var err error
|
||||||
|
for err == nil {
|
||||||
|
var line string
|
||||||
|
fmt.Print("\nmod> ")
|
||||||
|
line, err = r.ReadString(10)
|
||||||
|
if err == nil {
|
||||||
|
line = strings.Trim(line, "\n")
|
||||||
|
if line == "help" {
|
||||||
|
fmt.Println("usage:")
|
||||||
|
fmt.Println("delete <message-id>")
|
||||||
|
fmt.Println("overchan-inet-ban 1.1.1.1/32")
|
||||||
|
fmt.Println("exit")
|
||||||
|
} else if line == "quit" || line == "exit" {
|
||||||
|
fmt.Println("bai")
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
ev := srnd.ParseModEvent(line)
|
||||||
|
eng.Do(ev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if len(os.Args) >= 5 {
|
||||||
action := os.Args[3]
|
action := os.Args[3]
|
||||||
if action == "add" {
|
if action == "add" {
|
||||||
pk := os.Args[4]
|
pk := os.Args[4]
|
||||||
@ -62,9 +88,11 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(os.Stdout, "usage: %s tool mod [[add|del] pubkey]|[do modactiongoeshere]\n", os.Args[0])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(os.Stdout, "usage: %s tool mod [add|del] pubkey\n", os.Args[0])
|
fmt.Fprintf(os.Stdout, "usage: %s tool mod [[add|del] pubkey]|[do modactiongoeshere]\n", os.Args[0])
|
||||||
}
|
}
|
||||||
} else if tool == "rethumb" {
|
} else if tool == "rethumb" {
|
||||||
if len(os.Args) >= 4 {
|
if len(os.Args) >= 4 {
|
||||||
|
Reference in New Issue
Block a user