Add support for the user create admin service command
This adds support for user create, a new service command only accessible to admin users. This lets users create other users on the fly and makes soju start the user routine immediately; unlike sojuctl which currently requires closing soju, creating the user, and starting soju again.
This commit is contained in:
parent
f5611ae3f9
commit
5be25711c7
@ -138,6 +138,12 @@ abbreviated form, for instance *network* can be abbreviated as *net* or just
|
|||||||
Connect with the specified nickname. By default, the account's username
|
Connect with the specified nickname. By default, the account's username
|
||||||
is used.
|
is used.
|
||||||
|
|
||||||
|
*network delete* <name>
|
||||||
|
Disconnect and delete a network.
|
||||||
|
|
||||||
|
*network status*
|
||||||
|
Show a list of saved networks and their current status.
|
||||||
|
|
||||||
*certfp generate* *[options...]* <network name>
|
*certfp generate* *[options...]* <network name>
|
||||||
Generate self-signed certificate and use it for authentication.
|
Generate self-signed certificate and use it for authentication.
|
||||||
|
|
||||||
@ -159,15 +165,12 @@ abbreviated form, for instance *network* can be abbreviated as *net* or just
|
|||||||
*certfp reset* <network name>
|
*certfp reset* <network name>
|
||||||
Disable SASL EXTERNAL authentication and remove stored certificate.
|
Disable SASL EXTERNAL authentication and remove stored certificate.
|
||||||
|
|
||||||
|
*user create* -username <username> -password <password> [-admin]
|
||||||
|
Create a new soju user. Only admin users can create new accounts.
|
||||||
|
|
||||||
*change-password* <new password>
|
*change-password* <new password>
|
||||||
Change current user password.
|
Change current user password.
|
||||||
|
|
||||||
*network delete* <name>
|
|
||||||
Disconnect and delete a network.
|
|
||||||
|
|
||||||
*network status*
|
|
||||||
Show a list of saved networks and their current status.
|
|
||||||
|
|
||||||
# AUTHORS
|
# AUTHORS
|
||||||
|
|
||||||
Maintained by Simon Ser <contact@emersion.fr>, who is assisted by other
|
Maintained by Simon Ser <contact@emersion.fr>, who is assisted by other
|
||||||
|
20
server.go
20
server.go
@ -88,6 +88,26 @@ func (s *Server) Run() error {
|
|||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) createUser(user *User) (*user, error) {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
if _, ok := s.users[user.Username]; ok {
|
||||||
|
return nil, fmt.Errorf("user %q already exists", user.Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.db.StoreUser(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not create user in db: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Logger.Printf("starting bouncer for new user %q", user.Username)
|
||||||
|
u := newUser(s, user)
|
||||||
|
s.users[u.Username] = u
|
||||||
|
go u.run()
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) getUser(name string) *user {
|
func (s *Server) getUser(name string) *user {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
u := s.users[name]
|
u := s.users[name]
|
||||||
|
45
service.go
45
service.go
@ -162,6 +162,17 @@ func init() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"user": {
|
||||||
|
children: serviceCommandSet{
|
||||||
|
"create": {
|
||||||
|
usage: "-username <username> -password <password> [-admin]",
|
||||||
|
desc: "create a new soju user",
|
||||||
|
handle: handleUserCreate,
|
||||||
|
admin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
admin: true,
|
||||||
|
},
|
||||||
"change-password": {
|
"change-password": {
|
||||||
usage: "<new password>",
|
usage: "<new password>",
|
||||||
desc: "change your password",
|
desc: "change your password",
|
||||||
@ -567,3 +578,37 @@ func handlePasswordChange(dc *downstreamConn, params []string) error {
|
|||||||
sendServicePRIVMSG(dc, "password updated")
|
sendServicePRIVMSG(dc, "password updated")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleUserCreate(dc *downstreamConn, params []string) error {
|
||||||
|
fs := newFlagSet()
|
||||||
|
username := fs.String("username", "", "")
|
||||||
|
password := fs.String("password", "", "")
|
||||||
|
admin := fs.Bool("admin", false, "")
|
||||||
|
|
||||||
|
if err := fs.Parse(params); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if *username == "" {
|
||||||
|
return fmt.Errorf("flag -username is required")
|
||||||
|
}
|
||||||
|
if *password == "" {
|
||||||
|
return fmt.Errorf("flag -password is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
hashed, err := bcrypt.GenerateFromPassword([]byte(*password), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to hash password: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
user := &User{
|
||||||
|
Username: *username,
|
||||||
|
Password: string(hashed),
|
||||||
|
Admin: *admin,
|
||||||
|
}
|
||||||
|
if _, err := dc.srv.createUser(user); err != nil {
|
||||||
|
return fmt.Errorf("could not create user: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sendServicePRIVMSG(dc, fmt.Sprintf("created user %q", *username))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user