forked from External/grumble
User support in MurmurDB import and freezer.
This commit is contained in:
parent
73478072d0
commit
47bb4d0025
6 changed files with 223 additions and 16 deletions
1
Makefile
1
Makefile
|
|
@ -33,6 +33,7 @@ GOFILES = \
|
|||
channel.go \
|
||||
acl.go \
|
||||
group.go \
|
||||
user.go \
|
||||
murmurdb.go \
|
||||
freeze.go
|
||||
|
||||
|
|
|
|||
71
freeze.go
71
freeze.go
|
|
@ -1,3 +1,7 @@
|
|||
// Copyright (c) 2011 The Grumble Authors
|
||||
// The use of this source code is goverened by a BSD-style
|
||||
// license that can be found in the LICENSE-file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
|
@ -9,7 +13,20 @@ import (
|
|||
type frozenServer struct {
|
||||
Id int "id"
|
||||
MaxUsers int "max_user"
|
||||
SuperUserPassword string "super_user_password"
|
||||
Channels []frozenChannel "channels"
|
||||
Users []frozenUser "users"
|
||||
}
|
||||
|
||||
type frozenUser struct {
|
||||
Id uint32 "id"
|
||||
Name string "name"
|
||||
CertHash string "cert_hash"
|
||||
Email string "email"
|
||||
TextureBlob string "texture_blob"
|
||||
CommentBlob string "comment_blob"
|
||||
LastChannelId int "last_channel_id"
|
||||
LastActive uint64 "last_active"
|
||||
}
|
||||
|
||||
type frozenChannel struct {
|
||||
|
|
@ -21,8 +38,7 @@ type frozenChannel struct {
|
|||
Links []int "links"
|
||||
ACL []frozenACL "acl"
|
||||
Groups []frozenGroup "groups"
|
||||
Description string "description"
|
||||
DescriptionHash []byte "description_hash"
|
||||
DescriptionBlob string "description_blob"
|
||||
}
|
||||
|
||||
type frozenACL struct {
|
||||
|
|
@ -45,6 +61,7 @@ type frozenGroup struct {
|
|||
// Freeze a server
|
||||
func (server *Server) Freeze() (fs frozenServer, err os.Error) {
|
||||
fs.Id = int(server.Id)
|
||||
fs.SuperUserPassword = server.superUserPassword
|
||||
fs.MaxUsers = server.MaxUsers
|
||||
|
||||
channels := []frozenChannel{}
|
||||
|
|
@ -57,6 +74,16 @@ func (server *Server) Freeze() (fs frozenServer, err os.Error) {
|
|||
}
|
||||
fs.Channels = channels
|
||||
|
||||
users := []frozenUser{}
|
||||
for _, u := range server.Users {
|
||||
fu, err := u.Freeze()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users = append(users, fu)
|
||||
}
|
||||
fs.Users = users
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -71,8 +98,6 @@ func (channel *Channel) Freeze() (fc frozenChannel, err os.Error) {
|
|||
}
|
||||
fc.Position = int64(channel.Position)
|
||||
fc.InheritACL = channel.InheritACL
|
||||
fc.Description = channel.Description
|
||||
fc.DescriptionHash = channel.DescriptionHash
|
||||
|
||||
acls := []frozenACL{}
|
||||
for _, acl := range channel.ACL {
|
||||
|
|
@ -103,6 +128,20 @@ func (channel *Channel) Freeze() (fc frozenChannel, err os.Error) {
|
|||
return
|
||||
}
|
||||
|
||||
// Freeze a User
|
||||
func (user *User) Freeze() (fu frozenUser, err os.Error) {
|
||||
fu.Id = user.Id
|
||||
fu.Name = user.Name
|
||||
fu.CertHash = user.CertHash
|
||||
fu.Email = user.Email
|
||||
fu.TextureBlob = user.TextureBlob
|
||||
fu.CommentBlob = user.CommentBlob
|
||||
fu.LastChannelId = user.LastChannelId
|
||||
fu.LastActive = user.LastActive
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Freeze a ChannelACL
|
||||
func (acl *ChannelACL) Freeze() (facl frozenACL, err os.Error) {
|
||||
facl.UserId = acl.UserId
|
||||
|
|
@ -148,14 +187,15 @@ func NewServerFromFrozen(filename string) (s *Server, err os.Error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
s.superUserPassword = fs.SuperUserPassword
|
||||
|
||||
// Add all channels, but don't hook up parent/child relationships
|
||||
// until all of them are loaded.
|
||||
for _, jc := range fs.Channels {
|
||||
c := NewChannel(jc.Id, jc.Name)
|
||||
c.Position = int(jc.Position)
|
||||
c.InheritACL = jc.InheritACL
|
||||
c.Description = jc.Description
|
||||
c.DescriptionHash = jc.DescriptionHash
|
||||
c.DescriptionHash = []byte{} // fixme
|
||||
|
||||
for _, jacl := range jc.ACL {
|
||||
acl := NewChannelACL(c)
|
||||
|
|
@ -201,5 +241,24 @@ func NewServerFromFrozen(filename string) (s *Server, err os.Error) {
|
|||
|
||||
s.root = s.Channels[0]
|
||||
|
||||
// Add all users
|
||||
for _, ju := range fs.Users {
|
||||
u, err := NewUser(ju.Id, ju.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u.CertHash = ju.CertHash
|
||||
u.Email = ju.Email
|
||||
u.TextureBlob = ju.TextureBlob
|
||||
u.CommentBlob = ju.CommentBlob
|
||||
u.LastChannelId = ju.LastChannelId
|
||||
u.LastActive = ju.LastActive
|
||||
|
||||
s.Users[u.Id] = u
|
||||
s.UserNameMap[u.Name] = u
|
||||
s.UserCertMap[u.CertHash] = u
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
|
|
|||
11
grumble.go
11
grumble.go
|
|
@ -51,28 +51,25 @@ func MurmurImport(filename string) (err os.Error) {
|
|||
for _, sid := range servers {
|
||||
m, err := NewServerFromSQLite(sid, db)
|
||||
if err != nil {
|
||||
log.Printf("Unable to create server: %s", err.String())
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := os.Create(filepath.Join(*datadir, fmt.Sprintf("%v", sid)))
|
||||
if err != nil {
|
||||
log.Printf("%s", err.String())
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
zf, err := gzip.NewWriterLevel(f, gzip.BestCompression)
|
||||
|
||||
fz, err := m.Freeze()
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to freeze server: %s", err.String())
|
||||
return err
|
||||
}
|
||||
|
||||
enc := gob.NewEncoder(zf)
|
||||
err = enc.Encode(fz)
|
||||
if err != nil {
|
||||
log.Printf("%s", err.String())
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
zf.Close()
|
||||
|
|
|
|||
102
murmurdb.go
102
murmurdb.go
|
|
@ -1,3 +1,7 @@
|
|||
// Copyright (c) 2011 The Grumble Authors
|
||||
// The use of this source code is goverened by a BSD-style
|
||||
// license that can be found in the LICENSE-file.
|
||||
|
||||
package main
|
||||
|
||||
// This file implements a Server that can be created from a Murmur SQLite file.
|
||||
|
|
@ -42,6 +46,11 @@ func NewServerFromSQLite(id int64, db *sqlite.Conn) (s *Server, err os.Error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = populateUsers(s, db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -268,3 +277,96 @@ func populateChannelLinkInfo(server *Server, db *sqlite.Conn) (err os.Error) {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
|
||||
// Populate the server with regular user data
|
||||
stmt, err := db.Prepare("SELECT user_id, name, pw, lastchannel, texture, strftime('%s', last_active) FROM users WHERE server_id=?")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = stmt.Exec(server.Id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for stmt.Next() {
|
||||
var (
|
||||
UserId int64
|
||||
UserName string
|
||||
SHA1Password string
|
||||
LastChannel int
|
||||
Texture []byte
|
||||
LastActive int64
|
||||
)
|
||||
|
||||
err = stmt.Scan(&UserId, &UserName, &SHA1Password, &LastChannel, &Texture, &LastActive)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if UserId == 0 {
|
||||
server.superUserPassword = "sha1" + SHA1Password
|
||||
continue
|
||||
}
|
||||
|
||||
user, err := NewUser(uint32(UserId), UserName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user.LastActive = uint64(LastActive)
|
||||
user.LastChannelId = LastChannel
|
||||
|
||||
server.Users[user.Id] = user
|
||||
}
|
||||
|
||||
stmt, err = db.Prepare("SELECT key, value FROM user_info WHERE server_id=? AND user_id=?")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Populate users with any new-style UserInfo records
|
||||
for uid, user := range server.Users {
|
||||
err = stmt.Reset()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = stmt.Exec(server.Id, uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for stmt.Next() {
|
||||
var (
|
||||
Key int
|
||||
Value string
|
||||
)
|
||||
|
||||
err = stmt.Scan(&Key, &Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch Key {
|
||||
case UserInfoEmail:
|
||||
user.Email = Value
|
||||
case UserInfoComment:
|
||||
// unhandled
|
||||
case UserInfoHash:
|
||||
user.CertHash = "sha1-" + Value
|
||||
case UserInfoLastActive:
|
||||
// not a kv-pair (trigger)
|
||||
case UserInfoPassword:
|
||||
// not a kv-pair
|
||||
case UserInfoName:
|
||||
// not a kv-pair
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@ type Server struct {
|
|||
root *Channel
|
||||
Channels map[int]*Channel
|
||||
|
||||
// Users
|
||||
superUserPassword string
|
||||
Users map[uint32]*User
|
||||
UserCertMap map[string]*User
|
||||
UserNameMap map[string]*User
|
||||
|
||||
// ACL cache
|
||||
aclcache ACLCache
|
||||
}
|
||||
|
|
@ -81,6 +87,9 @@ func NewServer(id int64, addr string, port int) (s *Server, err os.Error) {
|
|||
s.port = port
|
||||
|
||||
s.clients = make(map[uint32]*Client)
|
||||
s.Users = make(map[uint32]*User)
|
||||
s.UserCertMap = make(map[string]*User)
|
||||
s.UserNameMap = make(map[string]*User)
|
||||
|
||||
s.hclients = make(map[string][]*Client)
|
||||
s.hpclients = make(map[string]*Client)
|
||||
|
|
|
|||
39
user.go
Normal file
39
user.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) 2011 The Grumble Authors
|
||||
// The use of this source code is goverened by a BSD-style
|
||||
// license that can be found in the LICENSE-file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// This file implements Server's handling of Users.
|
||||
//
|
||||
// Users are registered clients on the server.
|
||||
|
||||
type User struct {
|
||||
Id uint32
|
||||
Name string
|
||||
CertHash string
|
||||
Email string
|
||||
TextureBlob string
|
||||
CommentBlob string
|
||||
LastChannelId int
|
||||
LastActive uint64
|
||||
}
|
||||
|
||||
// Create a new User
|
||||
func NewUser(id uint32, name string) (user *User, err os.Error) {
|
||||
if id < 0 {
|
||||
return nil, os.NewError("Invalid user id")
|
||||
}
|
||||
if len(name) == 0 || name == "SuperUser" {
|
||||
return nil, os.NewError("Invalid username")
|
||||
}
|
||||
|
||||
return &User{
|
||||
Id: id,
|
||||
Name: name,
|
||||
}, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue