Started reworking skaldctl. Give room status along with room name.

This commit is contained in:
Storm Dragon
2026-05-30 22:46:32 -04:00
parent 4f35f4b933
commit 26c7808587
15 changed files with 639 additions and 556 deletions
+45 -2
View File
@@ -18,6 +18,13 @@ import (
var ErrTagMismatch = errors.New("tag mismatch")
var ErrDescriptionsNotWritable = &NotAuthorisedError{}
var ErrUnknownPermission = errors.New("unknown permission")
var localAdministration bool
// SetLocalAdministration allows a local administration tool to update hall
// files without enabling writes through the server's HTTP API.
func SetLocalAdministration(enabled bool) {
localAdministration = enabled
}
type Permissions struct {
// non-empty for a named permissions set
@@ -338,6 +345,9 @@ func makeETag(fileSize int64, modTime time.Time) string {
// DeleteDescription deletes a description (and therefore persistently
// deletes a hall) but only if it matches a given ETag.
func DeleteDescription(name, etag string) error {
if !validHallName(name) {
return UserError("illegal hall name")
}
halls.mu.Lock()
defer halls.mu.Unlock()
@@ -357,7 +367,22 @@ func UpdateDescription(name, etag string, desc *Description) error {
if desc.Users != nil || desc.WildcardUser != nil || desc.AuthKeys != nil {
return errors.New("description is not sanitised")
}
return updateDescription(name, etag, desc, true)
}
// WriteDescription writes a full hall description from a local administration
// tool. It is not available to the server's HTTP API.
func WriteDescription(name, etag string, desc *Description) error {
if !localAdministration {
return ErrDescriptionsNotWritable
}
return updateDescription(name, etag, desc, false)
}
func updateDescription(name, etag string, desc *Description, preserveSecrets bool) error {
if !validHallName(name) {
return UserError("illegal hall name")
}
halls.mu.Lock()
defer halls.mu.Unlock()
@@ -381,7 +406,7 @@ func UpdateDescription(name, etag string, desc *Description) error {
}
newdesc := *desc
if old != nil {
if old != nil && preserveSecrets {
newdesc.Users = old.Users
newdesc.WildcardUser = old.WildcardUser
newdesc.AuthKeys = old.AuthKeys
@@ -395,7 +420,7 @@ func rewriteDescriptionFile(filename string, desc *Description) error {
if err != nil {
return err
}
if !conf.WritableHalls {
if !conf.WritableHalls && !localAdministration {
return ErrDescriptionsNotWritable
}
@@ -657,9 +682,15 @@ func GetUserTag(hall, username string, wildcard bool) (string, error) {
}
func DeleteUser(hall, username string, wildcard bool, etag string) error {
if !validHallName(hall) {
return UserError("illegal hall name")
}
if wildcard && username != "" {
return errors.New("wildcard with username")
}
if !wildcard && !validUsername(username) {
return UserError("illegal username")
}
halls.mu.Lock()
defer halls.mu.Unlock()
@@ -698,9 +729,15 @@ func DeleteUser(hall, username string, wildcard bool, etag string) error {
}
func UpdateUser(hall, username string, wildcard bool, etag string, user *UserDescription) error {
if !validHallName(hall) {
return UserError("illegal hall name")
}
if wildcard && username != "" {
return errors.New("wildcard with username")
}
if !wildcard && !validUsername(username) {
return UserError("illegal username")
}
if user.Password.Type != "" || user.Password.Key != nil {
return errors.New("user description is not sanitised")
}
@@ -750,9 +787,15 @@ func UpdateUser(hall, username string, wildcard bool, etag string, user *UserDes
}
func SetUserPassword(hall, username string, wildcard bool, pw Password) error {
if !validHallName(hall) {
return UserError("illegal hall name")
}
if wildcard && username != "" {
return errors.New("wildcard with username")
}
if !wildcard && !validUsername(username) {
return UserError("illegal username")
}
halls.mu.Lock()
defer halls.mu.Unlock()
+38
View File
@@ -263,6 +263,44 @@ func TestWritableHalls(t *testing.T) {
testUser(t, "", true)
}
func TestLocalAdministrationWritesFullDescription(t *testing.T) {
err := setupTest(t.TempDir(), t.TempDir(), false)
if err != nil {
t.Fatalf("setupTest: %v", err)
}
SetLocalAdministration(true)
defer SetLocalAdministration(false)
permissions, err := NewPermissions("op")
if err != nil {
t.Fatalf("NewPermissions: %v", err)
}
pw := "secret"
err = WriteDescription("test", "", &Description{
Autolock: true,
Users: map[string]UserDescription{
"Username": {
Password: Password{
Type: "plain",
Key: &pw,
},
Permissions: permissions,
},
},
})
if err != nil {
t.Fatalf("WriteDescription: %v", err)
}
desc, err := GetDescription("test")
if err != nil {
t.Fatalf("GetDescription: %v", err)
}
if !desc.Autolock || desc.Users["Username"].Permissions.String() != "op" {
t.Fatalf("description = %#v", desc)
}
}
func testUser(t *testing.T, username string, wildcard bool) {
_, _, err := GetSanitisedUser("test", username, wildcard)
if !errors.Is(err, os.ErrNotExist) {
+11
View File
@@ -405,6 +405,11 @@ func validHallName(name string) bool {
return s == "/"+name
}
// ValidHallName reports whether name is safe to use as a hall name.
func ValidHallName(name string) bool {
return validHallName(name)
}
func add(name string, desc *Description) (*Hall, []Client, error) {
if !validHallName(name) {
return nil, nil, UserError("illegal hall name")
@@ -1034,6 +1039,11 @@ func validUsername(username string) bool {
return username != "" && validHallName(username)
}
// ValidUsername reports whether username is safe to use as a login name.
func ValidUsername(username string) bool {
return validUsername(username)
}
// called locked
func (g *Hall) getPermission(creds ClientCredentials) (string, []string, error) {
desc := g.description
@@ -1097,6 +1107,7 @@ type Status struct {
AuthServer string `json:"authServer,omitempty"`
AuthPortal string `json:"authPortal,omitempty"`
Locked bool `json:"locked,omitempty"`
Recording bool `json:"recording,omitempty"`
ClientCount *int `json:"clientCount,omitempty"`
CanChangePassword bool `json:"canChangePassword,omitempty"`
}