- Timestamp:
- Oct 12, 2021, 7:11:14 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/soju.1.scd
r620 r625 323 323 Other options are: 324 324 325 *-admin* 325 *-admin* true|false 326 326 Make the new user an administrator. 327 327 … … 330 330 realname set for a network. 331 331 332 *user update* [-password <password>] [-realname <realname>] 333 Update the current user. The options are the same as the _user create_ 334 command. 332 *user update* [username] [options...] 333 Update a user. The options are the same as the _user create_ command. 334 335 If _username_ is omitted, the current user is updated. Only admins can 336 update other users. 337 338 Not all flags are valid in all contexts: 339 340 - The _-username_ flag is never valid, usernames are immutable. 341 - The _-realname_ flag is only valid when updating the current user. 342 - The _-admin_ flag is only valid when updating another user. 335 343 336 344 *user delete* <username> -
trunk/service.go
r615 r625 126 126 } 127 127 if cmd.admin && !dc.user.Admin { 128 sendServicePRIVMSG(dc, fmt.Sprintf(`error: you must be an admin to use this command`))128 sendServicePRIVMSG(dc, "error: you must be an admin to use this command") 129 129 return 130 130 } … … 767 767 } 768 768 769 func popArg(params []string) (string, []string) { 770 if len(params) > 0 && !strings.HasPrefix(params[0], "-") { 771 return params[0], params[1:] 772 } 773 return "", params 774 } 775 769 776 func handleUserUpdate(dc *downstreamConn, params []string) error { 770 777 var password, realname *string 778 var admin *bool 771 779 fs := newFlagSet() 772 780 fs.Var(stringPtrFlag{&password}, "password", "") 773 781 fs.Var(stringPtrFlag{&realname}, "realname", "") 774 782 fs.Var(boolPtrFlag{&admin}, "admin", "") 783 784 username, params := popArg(params) 775 785 if err := fs.Parse(params); err != nil { 776 786 return err 777 787 } 778 779 // copy the user record because we'll mutate it 780 record := dc.user.User 781 788 if len(fs.Args()) > 0 { 789 return fmt.Errorf("unexpected argument") 790 } 791 792 var hashed *string 782 793 if password != nil { 783 hashed , err := bcrypt.GenerateFromPassword([]byte(*password), bcrypt.DefaultCost)794 hashedBytes, err := bcrypt.GenerateFromPassword([]byte(*password), bcrypt.DefaultCost) 784 795 if err != nil { 785 796 return fmt.Errorf("failed to hash password: %v", err) 786 797 } 787 record.Password = string(hashed) 788 } 789 if realname != nil { 790 record.Realname = *realname 791 } 792 793 if err := dc.user.updateUser(&record); err != nil { 794 return err 795 } 796 797 sendServicePRIVMSG(dc, fmt.Sprintf("updated user %q", dc.user.Username)) 798 hashedStr := string(hashedBytes) 799 hashed = &hashedStr 800 } 801 802 if username != "" && username != dc.user.Username { 803 if !dc.user.Admin { 804 return fmt.Errorf("you must be an admin to update other users") 805 } 806 if realname != nil { 807 return fmt.Errorf("cannot update -realname of other user") 808 } 809 810 u := dc.srv.getUser(username) 811 if u == nil { 812 return fmt.Errorf("unknown username %q", username) 813 } 814 815 done := make(chan error, 1) 816 u.events <- eventUserUpdate{ 817 password: hashed, 818 admin: admin, 819 done: done, 820 } 821 if err := <-done; err != nil { 822 return err 823 } 824 825 sendServicePRIVMSG(dc, fmt.Sprintf("updated user %q", username)) 826 } else { 827 // copy the user record because we'll mutate it 828 record := dc.user.User 829 830 if hashed != nil { 831 record.Password = *hashed 832 } 833 if realname != nil { 834 record.Realname = *realname 835 } 836 if admin != nil { 837 return fmt.Errorf("cannot update -admin of own user") 838 } 839 840 if err := dc.user.updateUser(&record); err != nil { 841 return err 842 } 843 844 sendServicePRIVMSG(dc, fmt.Sprintf("updated user %q", dc.user.Username)) 845 } 846 798 847 return nil 799 848 } -
trunk/user.go
r612 r625 59 59 60 60 type eventStop struct{} 61 62 type eventUserUpdate struct { 63 password *string 64 admin *bool 65 done chan error 66 } 61 67 62 68 type deliveredClientMap map[string]string // client name -> msg ID … … 643 649 dc.SendMessage(msg) 644 650 }) 651 case eventUserUpdate: 652 // copy the user record because we'll mutate it 653 record := u.User 654 655 if e.password != nil { 656 record.Password = *e.password 657 } 658 if e.admin != nil { 659 record.Admin = *e.admin 660 } 661 662 e.done <- u.updateUser(&record) 663 664 // If the password was updated, kill all downstream connections to 665 // force them to re-authenticate with the new credentials. 666 if e.password != nil { 667 u.forEachDownstream(func(dc *downstreamConn) { 668 dc.Close() 669 }) 670 } 645 671 case eventStop: 646 672 u.forEachDownstream(func(dc *downstreamConn) {
Note:
See TracChangeset
for help on using the changeset viewer.