mirror of
https://github.com/mumble-voip/grumble.git
synced 2025-12-20 06:10:00 -08:00
Registration support.
This commit is contained in:
parent
95509f9138
commit
28a74743a6
4 changed files with 130 additions and 17 deletions
|
|
@ -60,6 +60,7 @@ type Client struct {
|
|||
Username string
|
||||
Session uint32
|
||||
CertHash string
|
||||
Email string
|
||||
Tokens []string
|
||||
Channel *Channel
|
||||
SelfMute bool
|
||||
|
|
|
|||
|
|
@ -292,6 +292,9 @@ func NewServerFromFrozen(filename string) (s *Server, err os.Error) {
|
|||
u.LastActive = fu.LastActive
|
||||
|
||||
s.Users[u.Id] = u
|
||||
if u.Id > s.nextUserId {
|
||||
s.nextUserId = u.Id + 1
|
||||
}
|
||||
s.UserNameMap[u.Name] = u
|
||||
if len(u.CertHash) > 0 {
|
||||
s.UserCertMap[u.CertHash] = u
|
||||
|
|
|
|||
85
message.go
85
message.go
|
|
@ -601,21 +601,19 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
|
|||
if userstate.UserId != nil {
|
||||
// If user == actor, check for SelfRegisterPermission on root channel.
|
||||
// If user != actor, check for RegisterPermission permission on root channel.
|
||||
permCheck := Permission(NonePermission)
|
||||
uid := *userstate.UserId
|
||||
if target == actor {
|
||||
permCheck = SelfRegisterPermission
|
||||
} else {
|
||||
permCheck = RegisterPermission
|
||||
perm := Permission(RegisterPermission)
|
||||
if actor == target {
|
||||
perm = Permission(SelfRegisterPermission)
|
||||
}
|
||||
if uid >= 0 || !server.HasPermission(actor, server.root, SelfRegisterPermission) {
|
||||
client.sendPermissionDenied(actor, server.root, permCheck)
|
||||
|
||||
if target.IsRegistered() || !server.HasPermission(actor, server.root, perm) {
|
||||
client.sendPermissionDenied(actor, server.root, perm)
|
||||
return
|
||||
}
|
||||
|
||||
// We can't register a user with an empty hash.
|
||||
if len(target.CertHash) == 0 {
|
||||
client.sendPermissionDeniedTypeUser("MissingCertificate", target)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -733,10 +731,17 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
|
|||
broadcast = true
|
||||
}
|
||||
|
||||
userRegistrationChanged := false
|
||||
if userstate.UserId != nil {
|
||||
// fixme(mkrautz): Registration is currently unhandled.
|
||||
log.Printf("handleUserState: (Self)Register not implemented yet!")
|
||||
userstate.UserId = nil
|
||||
uid := server.RegisterClient(client)
|
||||
if uid > 0 {
|
||||
userstate.UserId = proto.Uint32(uid)
|
||||
client.user = server.Users[uid]
|
||||
userRegistrationChanged = true
|
||||
} else {
|
||||
userstate.UserId = nil
|
||||
}
|
||||
broadcast = true
|
||||
}
|
||||
|
||||
if userstate.ChannelId != nil {
|
||||
|
|
@ -799,6 +804,10 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
|
|||
userstate.CommentHash = nil
|
||||
}
|
||||
|
||||
if userRegistrationChanged {
|
||||
server.ClearACLCache()
|
||||
}
|
||||
|
||||
err := server.broadcastProtoMessageWithPredicate(MessageUserState, userstate, func(client *Client) bool {
|
||||
return client.Version >= 0x10203
|
||||
})
|
||||
|
|
@ -1198,3 +1207,55 @@ func (server *Server) handleRequestBlob(client *Client, msg *Message) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// User list query, user rename, user de-register
|
||||
func (server *Server) handleUserList(client *Client, msg *Message) {
|
||||
userlist := &mumbleproto.UserList{}
|
||||
err := proto.Unmarshal(msg.buf, userlist)
|
||||
if err != nil {
|
||||
client.Panic(err.String())
|
||||
return
|
||||
}
|
||||
|
||||
// Only users who are allowed to register other users can access the user list.
|
||||
if !server.HasPermission(client, server.root, RegisterPermission) {
|
||||
client.sendPermissionDenied(client, server.root, RegisterPermission)
|
||||
return
|
||||
}
|
||||
|
||||
// Query user list
|
||||
if len(userlist.Users) == 0 {
|
||||
for uid, user := range server.Users {
|
||||
if uid == 0 {
|
||||
continue
|
||||
}
|
||||
userlist.Users = append(userlist.Users, &mumbleproto.UserList_User{
|
||||
UserId: proto.Uint32(uid),
|
||||
Name: proto.String(user.Name),
|
||||
})
|
||||
}
|
||||
if err := client.sendProtoMessage(MessageUserList, userlist); err != nil {
|
||||
client.Panic(err.String())
|
||||
return
|
||||
}
|
||||
// Rename, registration removal
|
||||
} else {
|
||||
for _, listUser := range userlist.Users {
|
||||
uid := *listUser.UserId
|
||||
if uid == 0 {
|
||||
continue
|
||||
}
|
||||
// De-register a user
|
||||
if listUser.Name == nil {
|
||||
server.RemoveRegistration(uid)
|
||||
// Rename user
|
||||
} else {
|
||||
// todo(mkrautz): Validate name.
|
||||
user, ok := server.Users[uid]
|
||||
if ok {
|
||||
user.Name = *listUser.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
58
server.go
58
server.go
|
|
@ -84,6 +84,7 @@ type Server struct {
|
|||
Users map[uint32]*User
|
||||
UserCertMap map[string]*User
|
||||
UserNameMap map[string]*User
|
||||
nextUserId uint32
|
||||
|
||||
// ACL cache
|
||||
aclcache ACLCache
|
||||
|
|
@ -537,6 +538,11 @@ func (server *Server) finishAuthenticate(client *Client) {
|
|||
Name: proto.String(client.ShownName()),
|
||||
ChannelId: proto.Uint32(0),
|
||||
}
|
||||
|
||||
if len(client.CertHash) > 0 {
|
||||
userstate.Hash = proto.String(client.CertHash)
|
||||
}
|
||||
|
||||
if client.IsRegistered() {
|
||||
userstate.UserId = proto.Uint32(uint32(client.UserId()))
|
||||
|
||||
|
|
@ -681,6 +687,10 @@ func (server *Server) sendUserList(client *Client) {
|
|||
ChannelId: proto.Uint32(uint32(connectedClient.Channel.Id)),
|
||||
}
|
||||
|
||||
if len(connectedClient.CertHash) > 0 {
|
||||
userstate.Hash = connectedClient.CertHash
|
||||
}
|
||||
|
||||
if connectedClient.IsRegistered() {
|
||||
userstate.UserId = proto.Uint32(uint32(connectedClient.UserId()))
|
||||
|
||||
|
|
@ -709,10 +719,6 @@ func (server *Server) sendUserList(client *Client) {
|
|||
userstate.Comment = proto.String(string(buf))
|
||||
}
|
||||
}
|
||||
|
||||
if len(connectedClient.user.CertHash) > 0 {
|
||||
userstate.Hash = proto.String(connectedClient.user.CertHash)
|
||||
}
|
||||
}
|
||||
|
||||
if connectedClient.Mute {
|
||||
|
|
@ -820,7 +826,7 @@ func (server *Server) handleIncomingMessage(client *Client, msg *Message) {
|
|||
case MessageContextAction:
|
||||
log.Printf("MessageContextAction from client")
|
||||
case MessageUserList:
|
||||
log.Printf("MessageUserList from client")
|
||||
server.handleUserList(msg.client, msg)
|
||||
case MessageVoiceTarget:
|
||||
log.Printf("MessageVoiceTarget from client")
|
||||
case MessagePermissionQuery:
|
||||
|
|
@ -1003,6 +1009,48 @@ func (s *Server) FreezeServer() io.ReadCloser {
|
|||
return fr.readCloser
|
||||
}
|
||||
|
||||
// Register a client on the server.
|
||||
func (s *Server) RegisterClient(client *Client) (uid uint32) {
|
||||
// Increment nextUserId only if registration succeeded.
|
||||
defer func() {
|
||||
if uid > 0 {
|
||||
s.nextUserId += 1
|
||||
}
|
||||
}()
|
||||
|
||||
user, err := NewUser(s.nextUserId, client.Username)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Grumble can only register users with certificates.
|
||||
if len(client.CertHash) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
user.Email = client.Email
|
||||
user.CertHash = client.CertHash
|
||||
|
||||
uid = s.nextUserId
|
||||
s.Users[uid] = user
|
||||
s.UserCertMap[client.CertHash] = user
|
||||
s.UserNameMap[client.Username] = user
|
||||
return uid
|
||||
}
|
||||
|
||||
// Remove a registered user.
|
||||
func (s *Server) RemoveRegistration(uid uint32) (err os.Error) {
|
||||
user, ok := s.Users[uid]
|
||||
if !ok {
|
||||
return os.NewError("Unknown user ID")
|
||||
}
|
||||
|
||||
s.Users[uid] = nil, false
|
||||
s.UserCertMap[user.CertHash] = nil, false
|
||||
s.UserNameMap[user.Name] = nil, false
|
||||
return nil
|
||||
}
|
||||
|
||||
// The accept loop of the server.
|
||||
func (s *Server) ListenAndMurmur() {
|
||||
// Launch the event handler goroutine
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue