mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
commit
806c4b0d68
@ -1169,13 +1169,9 @@ func (vh *VHostInfo) checkThrottle(cooldown time.Duration) (err error) {
|
|||||||
// callback type implementing the actual business logic of vhost operations
|
// callback type implementing the actual business logic of vhost operations
|
||||||
type vhostMunger func(input VHostInfo) (output VHostInfo, err error)
|
type vhostMunger func(input VHostInfo) (output VHostInfo, err error)
|
||||||
|
|
||||||
func (am *AccountManager) VHostSet(account string, vhost string, cooldown time.Duration) (result VHostInfo, err error) {
|
func (am *AccountManager) VHostSet(account string, vhost string) (result VHostInfo, err error) {
|
||||||
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
||||||
output = input
|
output = input
|
||||||
err = output.checkThrottle(cooldown)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output.Enabled = true
|
output.Enabled = true
|
||||||
output.ApprovedVHost = vhost
|
output.ApprovedVHost = vhost
|
||||||
return
|
return
|
||||||
@ -1187,6 +1183,10 @@ func (am *AccountManager) VHostSet(account string, vhost string, cooldown time.D
|
|||||||
func (am *AccountManager) VHostRequest(account string, vhost string, cooldown time.Duration) (result VHostInfo, err error) {
|
func (am *AccountManager) VHostRequest(account string, vhost string, cooldown time.Duration) (result VHostInfo, err error) {
|
||||||
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
||||||
output = input
|
output = input
|
||||||
|
if input.Forbidden {
|
||||||
|
err = errVhostsForbidden
|
||||||
|
return
|
||||||
|
}
|
||||||
// you can update your existing request, but if you were approved or rejected,
|
// you can update your existing request, but if you were approved or rejected,
|
||||||
// you can't spam a new request
|
// you can't spam a new request
|
||||||
if output.RequestedVHost == "" {
|
if output.RequestedVHost == "" {
|
||||||
@ -1205,6 +1205,32 @@ func (am *AccountManager) VHostRequest(account string, vhost string, cooldown ti
|
|||||||
return am.performVHostChange(account, munger)
|
return am.performVHostChange(account, munger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (am *AccountManager) VHostTake(account string, vhost string, cooldown time.Duration) (result VHostInfo, err error) {
|
||||||
|
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
||||||
|
output = input
|
||||||
|
if input.Forbidden {
|
||||||
|
err = errVhostsForbidden
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if you have a request pending, you can cancel it using take;
|
||||||
|
// otherwise, you're subject to the same throttling as if you were making a request
|
||||||
|
if output.RequestedVHost == "" {
|
||||||
|
err = output.checkThrottle(cooldown)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output.ApprovedVHost = vhost
|
||||||
|
output.RequestedVHost = ""
|
||||||
|
output.RejectedVHost = ""
|
||||||
|
output.RejectionReason = ""
|
||||||
|
output.LastRequestTime = time.Now().UTC()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return am.performVHostChange(account, munger)
|
||||||
|
}
|
||||||
|
|
||||||
func (am *AccountManager) VHostApprove(account string) (result VHostInfo, err error) {
|
func (am *AccountManager) VHostApprove(account string) (result VHostInfo, err error) {
|
||||||
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
||||||
output = input
|
output = input
|
||||||
|
@ -50,6 +50,7 @@ var (
|
|||||||
errBanned = errors.New("IP or nickmask banned")
|
errBanned = errors.New("IP or nickmask banned")
|
||||||
errInvalidParams = utils.ErrInvalidParams
|
errInvalidParams = utils.ErrInvalidParams
|
||||||
errNoVhost = errors.New(`You do not have an approved vhost`)
|
errNoVhost = errors.New(`You do not have an approved vhost`)
|
||||||
|
errVhostsForbidden = errors.New(`An administrator has denied you the ability to use vhosts`)
|
||||||
errLimitExceeded = errors.New("Limit exceeded")
|
errLimitExceeded = errors.New("Limit exceeded")
|
||||||
errNoop = errors.New("Action was a no-op")
|
errNoop = errors.New("Action was a no-op")
|
||||||
errCASFailed = errors.New("Compare-and-swap update of database value failed")
|
errCASFailed = errors.New("Compare-and-swap update of database value failed")
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/oragono/oragono/irc/sno"
|
||||||
)
|
)
|
||||||
|
|
||||||
const hostservHelp = `HostServ lets you manage your vhost (i.e., the string displayed
|
const hostservHelp = `HostServ lets you manage your vhost (i.e., the string displayed
|
||||||
@ -216,6 +218,8 @@ func hsRequestHandler(server *Server, client *Client, command string, params []s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if throttled, ok := err.(*vhostThrottleExceeded); ok {
|
if throttled, ok := err.(*vhostThrottleExceeded); ok {
|
||||||
hsNotice(rb, fmt.Sprintf(client.t("You must wait an additional %v before making another request"), throttled.timeRemaining))
|
hsNotice(rb, fmt.Sprintf(client.t("You must wait an additional %v before making another request"), throttled.timeRemaining))
|
||||||
|
} else if err == errVhostsForbidden {
|
||||||
|
hsNotice(rb, client.t("An administrator has denied you the ability to use vhosts"))
|
||||||
} else {
|
} else {
|
||||||
hsNotice(rb, client.t("An error occurred"))
|
hsNotice(rb, client.t("An error occurred"))
|
||||||
}
|
}
|
||||||
@ -223,7 +227,7 @@ func hsRequestHandler(server *Server, client *Client, command string, params []s
|
|||||||
hsNotice(rb, client.t("Your vhost request will be reviewed by an administrator"))
|
hsNotice(rb, client.t("Your vhost request will be reviewed by an administrator"))
|
||||||
chanMsg := fmt.Sprintf("Account %s requests vhost %s", accountName, vhost)
|
chanMsg := fmt.Sprintf("Account %s requests vhost %s", accountName, vhost)
|
||||||
hsNotifyChannel(server, chanMsg)
|
hsNotifyChannel(server, chanMsg)
|
||||||
// TODO send admins a snomask of some kind
|
server.snomasks.Send(sno.LocalVhosts, chanMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +302,7 @@ func hsSetHandler(server *Server, client *Client, command string, params []strin
|
|||||||
}
|
}
|
||||||
// else: command == "del", vhost == ""
|
// else: command == "del", vhost == ""
|
||||||
|
|
||||||
_, err := server.accounts.VHostSet(user, vhost, 0)
|
_, err := server.accounts.VHostSet(user, vhost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
hsNotice(rb, client.t("An error occurred"))
|
hsNotice(rb, client.t("An error occurred"))
|
||||||
} else if vhost != "" {
|
} else if vhost != "" {
|
||||||
@ -326,6 +330,7 @@ func hsApproveHandler(server *Server, client *Client, command string, params []s
|
|||||||
hsNotice(rb, fmt.Sprintf(client.t("Successfully approved vhost request for %s"), user))
|
hsNotice(rb, fmt.Sprintf(client.t("Successfully approved vhost request for %s"), user))
|
||||||
chanMsg := fmt.Sprintf("Oper %[1]s approved vhost %[2]s for account %[3]s", client.Nick(), vhostInfo.ApprovedVHost, user)
|
chanMsg := fmt.Sprintf("Oper %[1]s approved vhost %[2]s for account %[3]s", client.Nick(), vhostInfo.ApprovedVHost, user)
|
||||||
hsNotifyChannel(server, chanMsg)
|
hsNotifyChannel(server, chanMsg)
|
||||||
|
server.snomasks.Send(sno.LocalVhosts, chanMsg)
|
||||||
for _, client := range server.accounts.AccountToClients(user) {
|
for _, client := range server.accounts.AccountToClients(user) {
|
||||||
client.Notice(client.t("Your vhost request was approved by an administrator"))
|
client.Notice(client.t("Your vhost request was approved by an administrator"))
|
||||||
}
|
}
|
||||||
@ -346,6 +351,7 @@ func hsRejectHandler(server *Server, client *Client, command string, params []st
|
|||||||
hsNotice(rb, fmt.Sprintf(client.t("Successfully rejected vhost request for %s"), user))
|
hsNotice(rb, fmt.Sprintf(client.t("Successfully rejected vhost request for %s"), user))
|
||||||
chanMsg := fmt.Sprintf("Oper %s rejected vhost %s for account %s, with the reason: %v", client.Nick(), vhostInfo.RejectedVHost, user, reason)
|
chanMsg := fmt.Sprintf("Oper %s rejected vhost %s for account %s, with the reason: %v", client.Nick(), vhostInfo.RejectedVHost, user, reason)
|
||||||
hsNotifyChannel(server, chanMsg)
|
hsNotifyChannel(server, chanMsg)
|
||||||
|
server.snomasks.Send(sno.LocalVhosts, chanMsg)
|
||||||
for _, client := range server.accounts.AccountToClients(user) {
|
for _, client := range server.accounts.AccountToClients(user) {
|
||||||
if reason == "" {
|
if reason == "" {
|
||||||
client.Notice("Your vhost request was rejected by an administrator")
|
client.Notice("Your vhost request was rejected by an administrator")
|
||||||
@ -404,16 +410,18 @@ func hsTakeHandler(server *Server, client *Client, command string, params []stri
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := server.accounts.VHostSet(client.Account(), vhost, config.Accounts.VHosts.UserRequests.Cooldown)
|
account := client.Account()
|
||||||
|
_, err := server.accounts.VHostTake(account, vhost, config.Accounts.VHosts.UserRequests.Cooldown)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if throttled, ok := err.(*vhostThrottleExceeded); ok {
|
if throttled, ok := err.(*vhostThrottleExceeded); ok {
|
||||||
hsNotice(rb, fmt.Sprintf(client.t("You must wait an additional %v before taking a vhost"), throttled.timeRemaining))
|
hsNotice(rb, fmt.Sprintf(client.t("You must wait an additional %v before taking a vhost"), throttled.timeRemaining))
|
||||||
|
} else if err == errVhostsForbidden {
|
||||||
|
hsNotice(rb, client.t("An administrator has denied you the ability to use vhosts"))
|
||||||
} else {
|
} else {
|
||||||
hsNotice(rb, client.t("An error occurred"))
|
hsNotice(rb, client.t("An error occurred"))
|
||||||
}
|
}
|
||||||
} else if vhost != "" {
|
|
||||||
hsNotice(rb, client.t("Successfully set vhost"))
|
|
||||||
} else {
|
} else {
|
||||||
hsNotice(rb, client.t("Successfully cleared vhost"))
|
hsNotice(rb, client.t("Successfully set vhost"))
|
||||||
|
server.snomasks.Send(sno.LocalVhosts, fmt.Sprintf("Client %s (account %s) took vhost %s", client.Nick(), account, vhost))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ type Mask rune
|
|||||||
|
|
||||||
// Notice mask types
|
// Notice mask types
|
||||||
const (
|
const (
|
||||||
LocalAccouncements Mask = 'a'
|
LocalAnnouncements Mask = 'a'
|
||||||
LocalConnects Mask = 'c'
|
LocalConnects Mask = 'c'
|
||||||
LocalChannels Mask = 'j'
|
LocalChannels Mask = 'j'
|
||||||
LocalKills Mask = 'k'
|
LocalKills Mask = 'k'
|
||||||
@ -19,12 +19,13 @@ const (
|
|||||||
Stats Mask = 't'
|
Stats Mask = 't'
|
||||||
LocalAccounts Mask = 'u'
|
LocalAccounts Mask = 'u'
|
||||||
LocalXline Mask = 'x'
|
LocalXline Mask = 'x'
|
||||||
|
LocalVhosts Mask = 'v'
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// NoticeMaskNames has readable names for our snomask types.
|
// NoticeMaskNames has readable names for our snomask types.
|
||||||
NoticeMaskNames = map[Mask]string{
|
NoticeMaskNames = map[Mask]string{
|
||||||
LocalAccouncements: "ANNOUNCEMENT",
|
LocalAnnouncements: "ANNOUNCEMENT",
|
||||||
LocalConnects: "CONNECT",
|
LocalConnects: "CONNECT",
|
||||||
LocalChannels: "CHANNEL",
|
LocalChannels: "CHANNEL",
|
||||||
LocalKills: "KILL",
|
LocalKills: "KILL",
|
||||||
@ -34,11 +35,12 @@ var (
|
|||||||
Stats: "STATS",
|
Stats: "STATS",
|
||||||
LocalAccounts: "ACCOUNT",
|
LocalAccounts: "ACCOUNT",
|
||||||
LocalXline: "XLINE",
|
LocalXline: "XLINE",
|
||||||
|
LocalVhosts: "VHOST",
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidMasks contains the snomasks that we support.
|
// ValidMasks contains the snomasks that we support.
|
||||||
ValidMasks = map[Mask]bool{
|
ValidMasks = map[Mask]bool{
|
||||||
LocalAccouncements: true,
|
LocalAnnouncements: true,
|
||||||
LocalConnects: true,
|
LocalConnects: true,
|
||||||
LocalChannels: true,
|
LocalChannels: true,
|
||||||
LocalKills: true,
|
LocalKills: true,
|
||||||
@ -48,5 +50,6 @@ var (
|
|||||||
Stats: true,
|
Stats: true,
|
||||||
LocalAccounts: true,
|
LocalAccounts: true,
|
||||||
LocalXline: true,
|
LocalXline: true,
|
||||||
|
LocalVhosts: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -466,7 +466,7 @@ opers:
|
|||||||
vhost: "n"
|
vhost: "n"
|
||||||
|
|
||||||
# modes are the modes to auto-set upon opering-up
|
# modes are the modes to auto-set upon opering-up
|
||||||
modes: +is acjknoqtux
|
modes: +is acjknoqtuxv
|
||||||
|
|
||||||
# operators can be authenticated either by password (with the /OPER command),
|
# operators can be authenticated either by password (with the /OPER command),
|
||||||
# or by certificate fingerprint, or both. if a password hash is set, then a
|
# or by certificate fingerprint, or both. if a password hash is set, then a
|
||||||
|
Loading…
Reference in New Issue
Block a user