Quellcode durchsuchen

review fixes, bug fixes

tags/v0.12.0
Shivaram Lingamneni vor 6 Jahren
Ursprung
Commit
cc9941cb07
7 geänderte Dateien mit 121 neuen und 75 gelöschten Zeilen
  1. 34
    24
      irc/accounts.go
  2. 4
    8
      irc/client.go
  3. 15
    12
      irc/config.go
  4. 5
    2
      irc/gateways.go
  5. 36
    17
      irc/hostserv.go
  6. 2
    2
      irc/server.go
  7. 25
    10
      oragono.yaml

+ 34
- 24
irc/accounts.go Datei anzeigen

@@ -109,7 +109,7 @@ func (am *AccountManager) buildNickToAccountIndex() {
109 109
 }
110 110
 
111 111
 func (am *AccountManager) initVHostRequestQueue() {
112
-	if !am.server.AccountConfig().HostServ.Enabled {
112
+	if !am.server.AccountConfig().VHosts.Enabled {
113 113
 		return
114 114
 	}
115 115
 
@@ -642,10 +642,7 @@ func (am *AccountManager) Unregister(account string) error {
642 642
 		tx.Delete(credentialsKey)
643 643
 		tx.Delete(vhostKey)
644 644
 		_, err := tx.Delete(vhostQueueKey)
645
-		if err != nil {
646
-			// 2's complement decrement
647
-			atomic.AddUint64(&am.vhostRequestPendingCount, ^uint64(0))
648
-		}
645
+		am.decrementVHostQueueCount(casefoldedAccount, err)
649 646
 		return nil
650 647
 	})
651 648
 
@@ -737,7 +734,7 @@ type PendingVHostRequest struct {
737 734
 // callback type implementing the actual business logic of vhost operations
738 735
 type vhostMunger func(input VHostInfo) (output VHostInfo, err error)
739 736
 
740
-func (am *AccountManager) VHostSet(account string, vhost string) (err error) {
737
+func (am *AccountManager) VHostSet(account string, vhost string) (result VHostInfo, err error) {
741 738
 	munger := func(input VHostInfo) (output VHostInfo, err error) {
742 739
 		output = input
743 740
 		output.Enabled = true
@@ -748,7 +745,7 @@ func (am *AccountManager) VHostSet(account string, vhost string) (err error) {
748 745
 	return am.performVHostChange(account, munger)
749 746
 }
750 747
 
751
-func (am *AccountManager) VHostRequest(account string, vhost string) (err error) {
748
+func (am *AccountManager) VHostRequest(account string, vhost string) (result VHostInfo, err error) {
752 749
 	munger := func(input VHostInfo) (output VHostInfo, err error) {
753 750
 		output = input
754 751
 		output.RequestedVHost = vhost
@@ -761,7 +758,7 @@ func (am *AccountManager) VHostRequest(account string, vhost string) (err error)
761 758
 	return am.performVHostChange(account, munger)
762 759
 }
763 760
 
764
-func (am *AccountManager) VHostApprove(account string) (err error) {
761
+func (am *AccountManager) VHostApprove(account string) (result VHostInfo, err error) {
765 762
 	munger := func(input VHostInfo) (output VHostInfo, err error) {
766 763
 		output = input
767 764
 		output.Enabled = true
@@ -774,7 +771,7 @@ func (am *AccountManager) VHostApprove(account string) (err error) {
774 771
 	return am.performVHostChange(account, munger)
775 772
 }
776 773
 
777
-func (am *AccountManager) VHostReject(account string, reason string) (err error) {
774
+func (am *AccountManager) VHostReject(account string, reason string) (result VHostInfo, err error) {
778 775
 	munger := func(input VHostInfo) (output VHostInfo, err error) {
779 776
 		output = input
780 777
 		output.RejectedVHost = output.RequestedVHost
@@ -786,7 +783,7 @@ func (am *AccountManager) VHostReject(account string, reason string) (err error)
786 783
 	return am.performVHostChange(account, munger)
787 784
 }
788 785
 
789
-func (am *AccountManager) VHostSetEnabled(client *Client, enabled bool) (err error) {
786
+func (am *AccountManager) VHostSetEnabled(client *Client, enabled bool) (result VHostInfo, err error) {
790 787
 	munger := func(input VHostInfo) (output VHostInfo, err error) {
791 788
 		output = input
792 789
 		output.Enabled = enabled
@@ -796,10 +793,11 @@ func (am *AccountManager) VHostSetEnabled(client *Client, enabled bool) (err err
796 793
 	return am.performVHostChange(client.Account(), munger)
797 794
 }
798 795
 
799
-func (am *AccountManager) performVHostChange(account string, munger vhostMunger) (err error) {
796
+func (am *AccountManager) performVHostChange(account string, munger vhostMunger) (result VHostInfo, err error) {
800 797
 	account, err = CasefoldName(account)
801 798
 	if err != nil || account == "" {
802
-		return errAccountDoesNotExist
799
+		err = errAccountDoesNotExist
800
+		return
803 801
 	}
804 802
 
805 803
 	am.vHostUpdateMutex.Lock()
@@ -807,19 +805,22 @@ func (am *AccountManager) performVHostChange(account string, munger vhostMunger)
807 805
 
808 806
 	clientAccount, err := am.LoadAccount(account)
809 807
 	if err != nil {
810
-		return errAccountDoesNotExist
808
+		err = errAccountDoesNotExist
809
+		return
811 810
 	} else if !clientAccount.Verified {
812
-		return errAccountUnverified
811
+		err = errAccountUnverified
812
+		return
813 813
 	}
814 814
 
815
-	result, err := munger(clientAccount.VHost)
815
+	result, err = munger(clientAccount.VHost)
816 816
 	if err != nil {
817
-		return err
817
+		return
818 818
 	}
819 819
 
820 820
 	vhtext, err := json.Marshal(result)
821 821
 	if err != nil {
822
-		return errAccountUpdateFailed
822
+		err = errAccountUpdateFailed
823
+		return
823 824
 	}
824 825
 	vhstr := string(vhtext)
825 826
 
@@ -839,21 +840,30 @@ func (am *AccountManager) performVHostChange(account string, munger vhostMunger)
839 840
 			atomic.AddUint64(&am.vhostRequestPendingCount, 1)
840 841
 		} else if clientAccount.VHost.RequestedVHost != "" && result.RequestedVHost == "" {
841 842
 			_, err = tx.Delete(queueKey)
842
-			if err != nil {
843
-				// XXX this is the decrement operation for two's complement
844
-				atomic.AddUint64(&am.vhostRequestPendingCount, ^uint64(0))
845
-			}
843
+			am.decrementVHostQueueCount(account, err)
846 844
 		}
847 845
 
848 846
 		return nil
849 847
 	})
850 848
 
851 849
 	if err != nil {
852
-		return errAccountUpdateFailed
850
+		err = errAccountUpdateFailed
851
+		return
853 852
 	}
854 853
 
855 854
 	am.applyVhostToClients(account, result)
856
-	return nil
855
+	return result, nil
856
+}
857
+
858
+// XXX annoying helper method for keeping the queue count in sync with the DB
859
+// `err` is the buntdb error returned from deleting the queue key
860
+func (am *AccountManager) decrementVHostQueueCount(account string, err error) {
861
+	if err == nil {
862
+		// successfully deleted a queue entry, do a 2's complement decrement:
863
+		atomic.AddUint64(&am.vhostRequestPendingCount, ^uint64(0))
864
+	} else if err != buntdb.ErrNotFound {
865
+		am.server.logger.Error("internal", "buntdb dequeue error", account, err.Error())
866
+	}
857 867
 }
858 868
 
859 869
 func (am *AccountManager) VHostListRequests(limit int) (requests []PendingVHostRequest, total int) {
@@ -893,7 +903,7 @@ func (am *AccountManager) VHostListRequests(limit int) (requests []PendingVHostR
893 903
 func (am *AccountManager) applyVHostInfo(client *Client, info VHostInfo) {
894 904
 	// if hostserv is disabled in config, then don't grant vhosts
895 905
 	// that were previously approved while it was enabled
896
-	if !am.server.AccountConfig().HostServ.Enabled {
906
+	if !am.server.AccountConfig().VHosts.Enabled {
897 907
 		return
898 908
 	}
899 909
 

+ 4
- 8
irc/client.go Datei anzeigen

@@ -311,10 +311,6 @@ func (client *Client) Ping() {
311 311
 
312 312
 }
313 313
 
314
-//
315
-// server goroutine
316
-//
317
-
318 314
 // Register sets the client details as appropriate when entering the network.
319 315
 func (client *Client) Register() {
320 316
 	client.stateMutex.Lock()
@@ -584,8 +580,8 @@ func (client *Client) SetVHost(vhost string) (updated bool) {
584 580
 func (client *Client) updateNick(nick string) {
585 581
 	casefoldedName, err := CasefoldName(nick)
586 582
 	if err != nil {
587
-		log.Println(fmt.Sprintf("ERROR: Nick [%s] couldn't be casefolded... this should never happen. Printing stacktrace.", client.nick))
588
-		debug.PrintStack()
583
+		client.server.logger.Error("internal", "nick couldn't be casefolded", nick, err.Error())
584
+		return
589 585
 	}
590 586
 	client.stateMutex.Lock()
591 587
 	client.nick = nick
@@ -616,8 +612,8 @@ func (client *Client) updateNickMaskNoMutex() {
616 612
 	nickMaskString := fmt.Sprintf("%s!%s@%s", client.nick, client.username, client.hostname)
617 613
 	nickMaskCasefolded, err := Casefold(nickMaskString)
618 614
 	if err != nil {
619
-		log.Println(fmt.Sprintf("ERROR: Nickmask [%s] couldn't be casefolded... this should never happen. Printing stacktrace.", client.nickMaskString))
620
-		debug.PrintStack()
615
+		client.server.logger.Error("internal", "nickmask couldn't be casefolded", nickMaskString, err.Error())
616
+		return
621 617
 	}
622 618
 
623 619
 	client.nickMaskString = nickMaskString

+ 15
- 12
irc/config.go Datei anzeigen

@@ -64,7 +64,7 @@ type AccountConfig struct {
64 64
 	AuthenticationEnabled bool                  `yaml:"authentication-enabled"`
65 65
 	SkipServerPassword    bool                  `yaml:"skip-server-password"`
66 66
 	NickReservation       NickReservationConfig `yaml:"nick-reservation"`
67
-	HostServ              HostServConfig
67
+	VHosts                VHostConfig
68 68
 }
69 69
 
70 70
 // AccountRegistrationConfig controls account registration.
@@ -92,13 +92,16 @@ type AccountRegistrationConfig struct {
92 92
 	AllowMultiplePerConnection bool `yaml:"allow-multiple-per-connection"`
93 93
 }
94 94
 
95
-type HostServConfig struct {
96
-	Enabled             bool
97
-	UserRequestsEnabled bool `yaml:"user-requests-enabled"`
98
-	Cooldown            time.Duration
99
-	MaxVHostLen         int    `yaml:"max-vhost-len"`
100
-	ValidRegexpRaw      string `yaml:"valid-regexp"`
101
-	ValidRegexp         *regexp.Regexp
95
+type VHostConfig struct {
96
+	Enabled        bool
97
+	MaxLength      int    `yaml:"max-length"`
98
+	ValidRegexpRaw string `yaml:"valid-regexp"`
99
+	ValidRegexp    *regexp.Regexp
100
+	UserRequests   struct {
101
+		Enabled  bool
102
+		Channel  string
103
+		Cooldown time.Duration
104
+	} `yaml:"user-requests"`
102 105
 }
103 106
 
104 107
 type NickReservationMethod int
@@ -543,17 +546,17 @@ func LoadConfig(filename string) (config *Config, err error) {
543 546
 		}
544 547
 	}
545 548
 
546
-	rawRegexp := config.Accounts.HostServ.ValidRegexpRaw
549
+	rawRegexp := config.Accounts.VHosts.ValidRegexpRaw
547 550
 	if rawRegexp != "" {
548 551
 		regexp, err := regexp.Compile(rawRegexp)
549 552
 		if err == nil {
550
-			config.Accounts.HostServ.ValidRegexp = regexp
553
+			config.Accounts.VHosts.ValidRegexp = regexp
551 554
 		} else {
552 555
 			log.Printf("invalid vhost regexp: %s\n", err.Error())
553 556
 		}
554 557
 	}
555
-	if config.Accounts.HostServ.ValidRegexp == nil {
556
-		config.Accounts.HostServ.ValidRegexp = validVhostRegex
558
+	if config.Accounts.VHosts.ValidRegexp == nil {
559
+		config.Accounts.VHosts.ValidRegexp = defaultValidVhostRegex
557 560
 	}
558 561
 
559 562
 	maxSendQBytes, err := bytefmt.ToBytes(config.Server.MaxSendQString)

+ 5
- 2
irc/gateways.go Datei anzeigen

@@ -75,9 +75,12 @@ func (client *Client) ApplyProxiedIP(proxiedIP string, tls bool) (exiting bool)
75 75
 	}
76 76
 
77 77
 	// given IP is sane! override the client's current IP
78
+	rawHostname := utils.LookupHostname(proxiedIP)
79
+	client.stateMutex.Lock()
78 80
 	client.proxiedIP = parsedProxiedIP
79
-	client.rawHostname = utils.LookupHostname(proxiedIP)
80
-	client.hostname = client.rawHostname
81
+	client.rawHostname = rawHostname
82
+	client.stateMutex.Unlock()
83
+	// nickmask will be updated when the client completes registration
81 84
 
82 85
 	// set tls info
83 86
 	client.certfp = ""

+ 36
- 17
irc/hostserv.go Datei anzeigen

@@ -1,4 +1,4 @@
1
-// Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
1
+// Copyright (c) 2018 Shivaram Lingamneni <slingamn@cs.stanford.edu>
2 2
 // released under the MIT license
3 3
 
4 4
 package irc
@@ -26,16 +26,16 @@ var (
26 26
 	errVHostBadCharacters = errors.New("Vhost contains prohibited characters")
27 27
 	errVHostTooLong       = errors.New("Vhost is too long")
28 28
 	// ascii only for now
29
-	validVhostRegex = regexp.MustCompile(`^[0-9A-Za-z.\-_/]+$`)
29
+	defaultValidVhostRegex = regexp.MustCompile(`^[0-9A-Za-z.\-_/]+$`)
30 30
 )
31 31
 
32 32
 func hostservEnabled(server *Server) bool {
33
-	return server.AccountConfig().HostServ.Enabled
33
+	return server.AccountConfig().VHosts.Enabled
34 34
 }
35 35
 
36 36
 func hostservRequestsEnabled(server *Server) bool {
37 37
 	ac := server.AccountConfig()
38
-	return ac.HostServ.Enabled && ac.HostServ.UserRequestsEnabled
38
+	return ac.VHosts.Enabled && ac.VHosts.UserRequests.Enabled
39 39
 }
40 40
 
41 41
 var (
@@ -84,7 +84,7 @@ request for a new one.`,
84 84
 
85 85
 SET sets a user's vhost, bypassing the request system.`,
86 86
 			helpShort: `$bSET$b sets a user's vhost.`,
87
-			capabs:    []string{"hostserv"},
87
+			capabs:    []string{"vhosts"},
88 88
 			enabled:   hostservEnabled,
89 89
 		},
90 90
 		"del": {
@@ -93,7 +93,7 @@ SET sets a user's vhost, bypassing the request system.`,
93 93
 
94 94
 DEL sets a user's vhost, bypassing the request system.`,
95 95
 			helpShort: `$bDEL$b deletes a user's vhost.`,
96
-			capabs:    []string{"hostserv"},
96
+			capabs:    []string{"vhosts"},
97 97
 			enabled:   hostservEnabled,
98 98
 		},
99 99
 		"waiting": {
@@ -103,7 +103,7 @@ DEL sets a user's vhost, bypassing the request system.`,
103 103
 WAITING shows a list of pending vhost requests, which can then be approved
104 104
 or rejected.`,
105 105
 			helpShort: `$bWAITING$b shows a list of pending vhost requests.`,
106
-			capabs:    []string{"hostserv"},
106
+			capabs:    []string{"vhosts"},
107 107
 			enabled:   hostservEnabled,
108 108
 		},
109 109
 		"approve": {
@@ -112,7 +112,7 @@ or rejected.`,
112 112
 
113 113
 APPROVE approves a user's vhost request.`,
114 114
 			helpShort: `$bAPPROVE$b approves a user's vhost request.`,
115
-			capabs:    []string{"hostserv"},
115
+			capabs:    []string{"vhosts"},
116 116
 			enabled:   hostservEnabled,
117 117
 		},
118 118
 		"reject": {
@@ -122,7 +122,7 @@ APPROVE approves a user's vhost request.`,
122 122
 REJECT rejects a user's vhost request, optionally giving them a reason
123 123
 for the rejection.`,
124 124
 			helpShort: `$bREJECT$b rejects a user's vhost request.`,
125
-			capabs:    []string{"hostserv"},
125
+			capabs:    []string{"vhosts"},
126 126
 			enabled:   hostservEnabled,
127 127
 		},
128 128
 	}
@@ -133,13 +133,26 @@ func hsNotice(rb *ResponseBuffer, text string) {
133 133
 	rb.Add(nil, "HostServ", "NOTICE", rb.target.Nick(), text)
134 134
 }
135 135
 
136
+// hsNotifyChannel notifies the designated channel of new vhost activity
137
+func hsNotifyChannel(server *Server, message string) {
138
+	chname := server.AccountConfig().VHosts.UserRequests.Channel
139
+	channel := server.channels.Get(chname)
140
+	if channel == nil {
141
+		return
142
+	}
143
+	chname = channel.Name()
144
+	for _, client := range channel.Members() {
145
+		client.Send(nil, "HostServ", "PRIVMSG", chname, message)
146
+	}
147
+}
148
+
136 149
 func hsOnOffHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
137 150
 	enable := false
138 151
 	if command == "on" {
139 152
 		enable = true
140 153
 	}
141 154
 
142
-	err := server.accounts.VHostSetEnabled(client, enable)
155
+	_, err := server.accounts.VHostSetEnabled(client, enable)
143 156
 	if err != nil {
144 157
 		hsNotice(rb, client.t("An error occurred"))
145 158
 	} else if enable {
@@ -163,7 +176,7 @@ func hsRequestHandler(server *Server, client *Client, command, params string, rb
163 176
 		return
164 177
 	}
165 178
 	elapsed := time.Now().Sub(account.VHost.LastRequestTime)
166
-	remainingTime := server.AccountConfig().HostServ.Cooldown - elapsed
179
+	remainingTime := server.AccountConfig().VHosts.UserRequests.Cooldown - elapsed
167 180
 	// you can update your existing request, but if you were rejected,
168 181
 	// you can't spam a replacement request
169 182
 	if account.VHost.RequestedVHost == "" && remainingTime > 0 {
@@ -171,11 +184,13 @@ func hsRequestHandler(server *Server, client *Client, command, params string, rb
171 184
 		return
172 185
 	}
173 186
 
174
-	err = server.accounts.VHostRequest(accountName, vhost)
187
+	_, err = server.accounts.VHostRequest(accountName, vhost)
175 188
 	if err != nil {
176 189
 		hsNotice(rb, client.t("An error occurred"))
177 190
 	} else {
178 191
 		hsNotice(rb, fmt.Sprintf(client.t("Your vhost request will be reviewed by an administrator")))
192
+		chanMsg := fmt.Sprintf("Account %s requests vhost %s", accountName, vhost)
193
+		hsNotifyChannel(server, chanMsg)
179 194
 		// TODO send admins a snomask of some kind
180 195
 	}
181 196
 }
@@ -208,10 +223,10 @@ func hsStatusHandler(server *Server, client *Client, command, params string, rb
208 223
 
209 224
 func validateVhost(server *Server, vhost string, oper bool) error {
210 225
 	ac := server.AccountConfig()
211
-	if len(vhost) > ac.HostServ.MaxVHostLen {
226
+	if len(vhost) > ac.VHosts.MaxLength {
212 227
 		return errVHostTooLong
213 228
 	}
214
-	if !ac.HostServ.ValidRegexp.MatchString(vhost) {
229
+	if !ac.VHosts.ValidRegexp.MatchString(vhost) {
215 230
 		return errVHostBadCharacters
216 231
 	}
217 232
 	return nil
@@ -235,7 +250,7 @@ func hsSetHandler(server *Server, client *Client, command, params string, rb *Re
235 250
 		return
236 251
 	}
237 252
 
238
-	err := server.accounts.VHostSet(user, vhost)
253
+	_, err := server.accounts.VHostSet(user, vhost)
239 254
 	if err != nil {
240 255
 		hsNotice(rb, client.t("An error occurred"))
241 256
 	} else if vhost != "" {
@@ -260,11 +275,13 @@ func hsApproveHandler(server *Server, client *Client, command, params string, rb
260 275
 		return
261 276
 	}
262 277
 
263
-	err := server.accounts.VHostApprove(user)
278
+	vhostInfo, err := server.accounts.VHostApprove(user)
264 279
 	if err != nil {
265 280
 		hsNotice(rb, client.t("An error occurred"))
266 281
 	} else {
267 282
 		hsNotice(rb, fmt.Sprintf(client.t("Successfully approved vhost request for %s"), user))
283
+		chanMsg := fmt.Sprintf("Oper %s approved vhost %s for account %s", client.Nick(), vhostInfo.ApprovedVHost, user)
284
+		hsNotifyChannel(server, chanMsg)
268 285
 		for _, client := range server.accounts.AccountToClients(user) {
269 286
 			client.Notice(client.t("Your vhost request was approved by an administrator"))
270 287
 		}
@@ -279,11 +296,13 @@ func hsRejectHandler(server *Server, client *Client, command, params string, rb
279 296
 	}
280 297
 	reason := strings.TrimSpace(params)
281 298
 
282
-	err := server.accounts.VHostReject(user, reason)
299
+	vhostInfo, err := server.accounts.VHostReject(user, reason)
283 300
 	if err != nil {
284 301
 		hsNotice(rb, client.t("An error occurred"))
285 302
 	} else {
286 303
 		hsNotice(rb, fmt.Sprintf(client.t("Successfully rejected vhost request for %s"), user))
304
+		chanMsg := fmt.Sprintf("Oper %s rejected vhost %s for account %s, with the reason: %v", client.Nick(), vhostInfo.RejectedVHost, user, reason)
305
+		hsNotifyChannel(server, chanMsg)
287 306
 		for _, client := range server.accounts.AccountToClients(user) {
288 307
 			if reason == "" {
289 308
 				client.Notice("Your vhost request was rejected by an administrator")

+ 2
- 2
irc/server.go Datei anzeigen

@@ -858,8 +858,8 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
858 858
 		server.accounts.buildNickToAccountIndex()
859 859
 	}
860 860
 
861
-	hsPreviouslyDisabled := oldAccountConfig != nil && !oldAccountConfig.HostServ.Enabled
862
-	hsNowEnabled := config.Accounts.HostServ.Enabled
861
+	hsPreviouslyDisabled := oldAccountConfig != nil && !oldAccountConfig.VHosts.Enabled
862
+	hsNowEnabled := config.Accounts.VHosts.Enabled
863 863
 	if hsPreviouslyDisabled && hsNowEnabled {
864 864
 		server.accounts.initVHostRequestQueue()
865 865
 	}

+ 25
- 10
oragono.yaml Datei anzeigen

@@ -198,21 +198,36 @@ accounts:
198 198
         # rename-prefix - this is the prefix to use when renaming clients (e.g. Guest-AB54U31)
199 199
         rename-prefix: Guest-
200 200
 
201
-    hostserv:
202
-        # is hostserv enabled at all?
201
+    # vhosts controls the assignment of vhosts (strings displayed in place of the user's
202
+    # hostname/IP) by the HostServ service
203
+    vhosts:
204
+        # are vhosts enabled at all?
203 205
         enabled: true
204
-        # can users request vhosts from operators? if this is false, operators with the
205
-        # "hostserv" capability can still assign vhosts manually:
206
-        user-requests-enabled: false
207
-        # to prevent users from spamming requests, they must wait at least this long between
208
-        # distinct requests:
209
-        cooldown: 1h
206
+
210 207
         # maximum length of a vhost
211
-        max-vhost-len: 64
208
+        max-length: 64
209
+
212 210
         # regexp for testing the validity of a vhost
213 211
         # (make sure any changes you make here are RFC-compliant)
214 212
         valid-regexp: '^[0-9A-Za-z.\-_/]+$'
215 213
 
214
+        # options controlling users requesting vhosts:
215
+        user-requests:
216
+            # can users request vhosts at all? if this is false, operators with the
217
+            # 'vhosts' capability can still assign vhosts manually
218
+            enabled: false
219
+
220
+            # if uncommented, all new vhost requests will be dumped into the given
221
+            # channel, so opers can review them as they are sent in. ensure that you
222
+            # have registered and restricted the channel appropriately before you
223
+            # uncomment this.
224
+            #channel: "#vhosts"
225
+
226
+            # after a user's vhost has been approved or rejected, they need to wait
227
+            # this long (starting from the time of their original request)
228
+            # before they can request a new one.
229
+            cooldown: 168h
230
+
216 231
 # channel options
217 232
 channels:
218 233
     # modes that are set when new channels are created
@@ -267,7 +282,7 @@ oper-classes:
267 282
             - "oper:die"
268 283
             - "unregister"
269 284
             - "samode"
270
-            - "hostserv"
285
+            - "vhosts"
271 286
 
272 287
 # ircd operators
273 288
 opers:

Laden…
Abbrechen
Speichern