mirror of
https://github.com/jech/galene.git
synced 2024-12-22 07:15:47 +01:00
Distinguish between no username and empty username.
This commit is contained in:
parent
a1c1345719
commit
aa53b78b2c
6 changed files with 66 additions and 46 deletions
|
@ -101,7 +101,7 @@ func (client *Client) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (client *Client) Kick(id, user, message string) error {
|
||||
func (client *Client) Kick(id string, user *string, message string) error {
|
||||
err := client.Close()
|
||||
group.DelClient(client)
|
||||
return err
|
||||
|
|
|
@ -83,7 +83,7 @@ type ClientPattern struct {
|
|||
|
||||
type ClientCredentials struct {
|
||||
System bool
|
||||
Username string
|
||||
Username *string
|
||||
Password string
|
||||
Token string
|
||||
}
|
||||
|
@ -100,5 +100,5 @@ type Client interface {
|
|||
RequestConns(target Client, g *Group, id string) error
|
||||
Joined(group, kind string) error
|
||||
PushClient(group, kind, id, username string, perms []string, data map[string]interface{}) error
|
||||
Kick(id, user, message string) error
|
||||
Kick(id string, user *string, message string) error
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ func (err UserError) Error() string {
|
|||
|
||||
type KickError struct {
|
||||
Id string
|
||||
Username string
|
||||
Username *string
|
||||
Message string
|
||||
}
|
||||
|
||||
|
@ -45,8 +45,8 @@ func (err KickError) Error() string {
|
|||
if err.Message != "" {
|
||||
m += " (" + err.Message + ")"
|
||||
}
|
||||
if err.Username != "" {
|
||||
m += " by " + err.Username
|
||||
if err.Username != nil && *err.Username != "" {
|
||||
m += " by " + *err.Username
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func (err ProtocolError) Error() string {
|
|||
|
||||
type ChatHistoryEntry struct {
|
||||
Id string
|
||||
User string
|
||||
User *string
|
||||
Time time.Time
|
||||
Kind string
|
||||
Value interface{}
|
||||
|
@ -625,9 +625,8 @@ func AddClient(group string, c Client, creds ClientCredentials) (*Group, error)
|
|||
c.PushClient(g.Name(), "add", c.Id(), u, p, s)
|
||||
for _, cc := range clients {
|
||||
pp := cc.Permissions()
|
||||
c.PushClient(
|
||||
g.Name(), "add", cc.Id(), cc.Username(), pp, cc.Data(),
|
||||
)
|
||||
uu := cc.Username()
|
||||
c.PushClient(g.Name(), "add", cc.Id(), uu, pp, cc.Data())
|
||||
cc.PushClient(g.Name(), "add", id, u, p, s)
|
||||
}
|
||||
|
||||
|
@ -679,7 +678,7 @@ func DelClient(c Client) {
|
|||
c.Joined(g.Name(), "leave")
|
||||
for _, cc := range clients {
|
||||
cc.PushClient(
|
||||
g.Name(), "delete", c.Id(), "", nil, nil,
|
||||
g.Name(), "delete", c.Id(), c.Username(), nil, nil,
|
||||
)
|
||||
}
|
||||
autoLockKick(g)
|
||||
|
@ -729,7 +728,7 @@ func (g *Group) Range(f func(c Client) bool) {
|
|||
|
||||
func kickall(g *Group, message string) {
|
||||
g.Range(func(c Client) bool {
|
||||
c.Kick("", "", message)
|
||||
c.Kick("", nil, message)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
@ -768,7 +767,7 @@ func (g *Group) ClearChatHistory() {
|
|||
g.history = nil
|
||||
}
|
||||
|
||||
func (g *Group) AddToChatHistory(id, user string, time time.Time, kind string, value interface{}) {
|
||||
func (g *Group) AddToChatHistory(id string, user *string, time time.Time, kind string, value interface{}) {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
|
||||
|
@ -810,9 +809,14 @@ func (g *Group) GetChatHistory() []ChatHistoryEntry {
|
|||
}
|
||||
|
||||
func matchClient(creds ClientCredentials, users []ClientPattern) (bool, bool) {
|
||||
if creds.Username == nil {
|
||||
return false, false
|
||||
}
|
||||
username := *creds.Username
|
||||
|
||||
matched := false
|
||||
for _, u := range users {
|
||||
if u.Username == creds.Username {
|
||||
if u.Username == username {
|
||||
matched = true
|
||||
if u.Password == nil {
|
||||
return true, true
|
||||
|
@ -1102,7 +1106,10 @@ func readDescription(name string) (*Description, error) {
|
|||
func (g *Group) getPasswordPermission(creds ClientCredentials) ([]string, error) {
|
||||
desc := g.description
|
||||
|
||||
if !desc.AllowAnonymous && creds.Username == "" {
|
||||
if creds.Username == nil {
|
||||
return nil, errors.New("username not provided")
|
||||
}
|
||||
if !desc.AllowAnonymous && *creds.Username == "" {
|
||||
return nil, ErrAnonymousNotAuthorised
|
||||
}
|
||||
if found, good := matchClient(creds, desc.Op); found {
|
||||
|
@ -1146,17 +1153,19 @@ func (g *Group) getPermission(creds ClientCredentials) (string, []string, error)
|
|||
}
|
||||
|
||||
username, perms, err =
|
||||
tok.Check(conf.CanonicalHost, g.name, &creds.Username)
|
||||
tok.Check(conf.CanonicalHost, g.name, creds.Username)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
} else {
|
||||
} else if creds.Username != nil {
|
||||
username = *creds.Username
|
||||
var err error
|
||||
username = creds.Username
|
||||
perms, err = g.getPasswordPermission(creds)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
} else {
|
||||
return "", nil, errors.New("neither username nor token provided")
|
||||
}
|
||||
|
||||
return username, perms, nil
|
||||
|
|
|
@ -51,8 +51,9 @@ func TestChatHistory(t *testing.T) {
|
|||
g := Group{
|
||||
description: &Description{},
|
||||
}
|
||||
user := "user"
|
||||
for i := 0; i < 2*maxChatHistory; i++ {
|
||||
g.AddToChatHistory("id", "user", time.Now(), "",
|
||||
g.AddToChatHistory("id", &user, time.Now(), "",
|
||||
fmt.Sprintf("%v", i),
|
||||
)
|
||||
}
|
||||
|
@ -108,10 +109,15 @@ func TestDescriptionJSON(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var jch = "jch"
|
||||
var john = "john"
|
||||
var james = "james"
|
||||
var paul = "paul"
|
||||
|
||||
var badClients = []ClientCredentials{
|
||||
{Username: "jch", Password: "foo"},
|
||||
{Username: "john", Password: "foo"},
|
||||
{Username: "james", Password: "foo"},
|
||||
{Username: &jch, Password: "foo"},
|
||||
{Username: &john, Password: "foo"},
|
||||
{Username: &james, Password: "foo"},
|
||||
}
|
||||
|
||||
type credPerm struct {
|
||||
|
@ -121,23 +127,23 @@ type credPerm struct {
|
|||
|
||||
var goodClients = []credPerm{
|
||||
{
|
||||
ClientCredentials{Username: "jch", Password: "topsecret"},
|
||||
ClientCredentials{Username: &jch, Password: "topsecret"},
|
||||
[]string{"op", "present"},
|
||||
},
|
||||
{
|
||||
ClientCredentials{Username: "john", Password: "secret"},
|
||||
ClientCredentials{Username: &john, Password: "secret"},
|
||||
[]string{"present"},
|
||||
},
|
||||
{
|
||||
ClientCredentials{Username: "john", Password: "secret2"},
|
||||
ClientCredentials{Username: &john, Password: "secret2"},
|
||||
[]string{"present"},
|
||||
},
|
||||
{
|
||||
ClientCredentials{Username: "james", Password: "secret3"},
|
||||
ClientCredentials{Username: &james, Password: "secret3"},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
ClientCredentials{Username: "paul", Password: "secret3"},
|
||||
ClientCredentials{Username: &paul, Password: "secret3"},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
@ -150,7 +156,7 @@ func TestPermissions(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, c := range badClients {
|
||||
t.Run("bad "+c.Username, func(t *testing.T) {
|
||||
t.Run("bad "+*c.Username, func(t *testing.T) {
|
||||
_, p, err := g.GetPermission(c)
|
||||
if err != ErrNotAuthorised {
|
||||
t.Errorf("GetPermission %v: %v %v", c, err, p)
|
||||
|
@ -159,11 +165,11 @@ func TestPermissions(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, cp := range goodClients {
|
||||
t.Run("good "+cp.c.Username, func(t *testing.T) {
|
||||
t.Run("good "+*cp.c.Username, func(t *testing.T) {
|
||||
u, p, err := g.GetPermission(cp.c)
|
||||
if err != nil {
|
||||
t.Errorf("GetPermission %v: %v", cp.c, err)
|
||||
} else if u != cp.c.Username ||
|
||||
} else if u != *cp.c.Username ||
|
||||
!reflect.DeepEqual(p, cp.p) {
|
||||
t.Errorf("%v: got %v %v, expected %v",
|
||||
cp.c, u, p, cp.p)
|
||||
|
|
|
@ -102,7 +102,7 @@ func (c *webClient) SetPermissions(perms []string) {
|
|||
c.permissions = perms
|
||||
}
|
||||
|
||||
func (c *webClient) PushClient(group, kind, id, username string, perms []string, data map[string]interface{}) error {
|
||||
func (c *webClient) PushClient(group, kind, id string, username string, perms []string, data map[string]interface{}) error {
|
||||
return c.action(pushClientAction{
|
||||
group, kind, id, username, perms, data,
|
||||
})
|
||||
|
@ -117,7 +117,7 @@ type clientMessage struct {
|
|||
Replace string `json:"replace,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
Dest string `json:"dest,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Username *string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Token string `json:"token,omitempty"`
|
||||
Privileged bool `json:"privileged,omitempty"`
|
||||
|
@ -555,7 +555,7 @@ func negotiate(c *webClient, down *rtpDownConnection, restartIce bool, replace s
|
|||
Label: down.remote.Label(),
|
||||
Replace: replace,
|
||||
Source: source,
|
||||
Username: username,
|
||||
Username: &username,
|
||||
SDP: down.pc.LocalDescription().SDP,
|
||||
})
|
||||
}
|
||||
|
@ -930,7 +930,7 @@ type joinedAction struct {
|
|||
|
||||
type kickAction struct {
|
||||
id string
|
||||
username string
|
||||
username *string
|
||||
message string
|
||||
}
|
||||
|
||||
|
@ -1160,11 +1160,12 @@ func handleAction(c *webClient, a interface{}) error {
|
|||
return nil
|
||||
}
|
||||
perms := append([]string(nil), a.permissions...)
|
||||
username := a.username
|
||||
return c.write(clientMessage{
|
||||
Type: "user",
|
||||
Kind: a.kind,
|
||||
Id: a.id,
|
||||
Username: a.username,
|
||||
Username: &username,
|
||||
Permissions: perms,
|
||||
Data: a.data,
|
||||
})
|
||||
|
@ -1181,11 +1182,12 @@ func handleAction(c *webClient, a interface{}) error {
|
|||
}
|
||||
}
|
||||
perms := append([]string(nil), c.permissions...)
|
||||
username := c.username
|
||||
err := c.write(clientMessage{
|
||||
Type: "joined",
|
||||
Kind: a.kind,
|
||||
Group: a.group,
|
||||
Username: c.username,
|
||||
Username: &username,
|
||||
Permissions: perms,
|
||||
Status: status,
|
||||
Data: data,
|
||||
|
@ -1222,11 +1224,12 @@ func handleAction(c *webClient, a interface{}) error {
|
|||
}
|
||||
perms := append([]string(nil), c.permissions...)
|
||||
status := g.Status(true, "")
|
||||
username := c.username
|
||||
c.write(clientMessage{
|
||||
Type: "joined",
|
||||
Kind: "change",
|
||||
Group: g.Name(),
|
||||
Username: c.username,
|
||||
Username: &username,
|
||||
Permissions: perms,
|
||||
Status: &status,
|
||||
RTCConfiguration: ice.ICEConfiguration(),
|
||||
|
@ -1360,7 +1363,7 @@ func setPermissions(g *group.Group, id string, perm string) error {
|
|||
return c.action(permissionsChangedAction{})
|
||||
}
|
||||
|
||||
func (c *webClient) Kick(id, user, message string) error {
|
||||
func (c *webClient) Kick(id string, user *string, message string) error {
|
||||
return c.action(kickAction{id, user, message})
|
||||
}
|
||||
|
||||
|
@ -1368,7 +1371,7 @@ func (c *webClient) Joined(group, kind string) error {
|
|||
return c.action(joinedAction{group, kind})
|
||||
}
|
||||
|
||||
func kickClient(g *group.Group, id, user, dest string, message string) error {
|
||||
func kickClient(g *group.Group, id string, user *string, dest string, message string) error {
|
||||
client := g.GetClient(dest)
|
||||
if client == nil {
|
||||
return group.UserError("no such user")
|
||||
|
@ -1385,8 +1388,8 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
|||
}
|
||||
|
||||
if m.Type != "join" {
|
||||
if m.Username != "" {
|
||||
if m.Username != c.Username() {
|
||||
if m.Username != nil {
|
||||
if *m.Username != c.Username() {
|
||||
return group.ProtocolError("spoofed username")
|
||||
}
|
||||
}
|
||||
|
@ -1411,7 +1414,6 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
|||
"cannot join multiple groups",
|
||||
)
|
||||
}
|
||||
c.username = m.Username
|
||||
c.data = m.Data
|
||||
g, err := group.AddClient(m.Group, c,
|
||||
group.ClientCredentials{
|
||||
|
@ -1435,23 +1437,25 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
|||
s = "internal server error"
|
||||
log.Printf("Join group: %v", err)
|
||||
}
|
||||
username := c.username
|
||||
return c.write(clientMessage{
|
||||
Type: "joined",
|
||||
Kind: "fail",
|
||||
Error: e,
|
||||
Group: m.Group,
|
||||
Username: c.username,
|
||||
Username: &username,
|
||||
Value: s,
|
||||
})
|
||||
}
|
||||
if redirect := g.Description().Redirect; redirect != "" {
|
||||
// We normally redirect at the HTTP level, but the group
|
||||
// description could have been edited in the meantime.
|
||||
username := c.username
|
||||
return c.write(clientMessage{
|
||||
Type: "joined",
|
||||
Kind: "redirect",
|
||||
Group: m.Group,
|
||||
Username: c.username,
|
||||
Username: &username,
|
||||
Value: redirect,
|
||||
})
|
||||
}
|
||||
|
@ -1677,10 +1681,11 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
|||
s = s + fmt.Sprintf("%v (%v client%v)\n",
|
||||
sg.Name, sg.Clients, plural)
|
||||
}
|
||||
username := "Server"
|
||||
c.write(clientMessage{
|
||||
Type: "chat",
|
||||
Dest: c.id,
|
||||
Username: "Server",
|
||||
Username: &username,
|
||||
Time: time.Now().Format(time.RFC3339),
|
||||
Value: s,
|
||||
})
|
||||
|
|
|
@ -642,7 +642,7 @@ func checkGroupPermissions(w http.ResponseWriter, r *http.Request, groupname str
|
|||
|
||||
_, p, err := g.GetPermission(
|
||||
group.ClientCredentials{
|
||||
Username: user,
|
||||
Username: &user,
|
||||
Password: pass,
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue