Handles PUT and POST for a user or a role.
(name string, isUser bool)
| 1799 | |
| 1800 | // Handles PUT and POST for a user or a role. |
| 1801 | func (h *handler) updatePrincipal(name string, isUser bool) error { |
| 1802 | h.assertAdminOnly() |
| 1803 | // Unmarshal the request body into a PrincipalConfig struct: |
| 1804 | body, _ := h.readBody() |
| 1805 | |
| 1806 | var newInfo auth.PrincipalConfig |
| 1807 | var err error |
| 1808 | if err = base.JSONUnmarshal(body, &newInfo); err != nil { |
| 1809 | return err |
| 1810 | } |
| 1811 | |
| 1812 | if h.rq.Method == "POST" { |
| 1813 | // On POST, take the name from the "name" property in the request body: |
| 1814 | if newInfo.Name == nil { |
| 1815 | return base.HTTPErrorf(http.StatusBadRequest, "Missing name property") |
| 1816 | } |
| 1817 | } else { |
| 1818 | // ON PUT, verify the name matches, if given: |
| 1819 | if newInfo.Name == nil { |
| 1820 | newInfo.Name = &name |
| 1821 | } else if *newInfo.Name != name { |
| 1822 | return base.HTTPErrorf(http.StatusBadRequest, "Name mismatch (can't change name)") |
| 1823 | } |
| 1824 | } |
| 1825 | |
| 1826 | // Check read only fields in request against existing read only fields on the user, if the request attempts to |
| 1827 | // change them, return error. |
| 1828 | internalName := internalUserName(*newInfo.Name) |
| 1829 | var unchanged bool |
| 1830 | user, _ := h.db.Authenticator(h.ctx()).GetUser(internalName) |
| 1831 | if user != nil { |
| 1832 | newInfo, unchanged = checkUserAPIReadOnlyFields(newInfo, user) |
| 1833 | if !unchanged { |
| 1834 | return base.HTTPErrorf(http.StatusBadRequest, "Can't change read-only properties") |
| 1835 | } |
| 1836 | } |
| 1837 | |
| 1838 | if err = auth.ValidatePrincipalName(internalName); err != nil { |
| 1839 | return base.NewHTTPError(http.StatusBadRequest, err.Error()) |
| 1840 | } |
| 1841 | |
| 1842 | newInfo.Name = &internalName |
| 1843 | replaced, princ, err := h.db.UpdatePrincipal(h.ctx(), &newInfo, isUser, h.rq.Method != "POST") |
| 1844 | if err != nil { |
| 1845 | return err |
| 1846 | } else if replaced { |
| 1847 | // update event |
| 1848 | if isUser { |
| 1849 | user := princ.(auth.User) |
| 1850 | if user != nil { |
| 1851 | base.Audit(h.ctx(), base.AuditIDUserUpdate, base.AuditFields{ |
| 1852 | "username": internalName, |
| 1853 | "roles": user.ExplicitRoles().AllKeys(), |
| 1854 | "channels": getAuditEventAccess(h.db, princ), |
| 1855 | "db": h.db.Name, |
| 1856 | }) |
| 1857 | } |
| 1858 | } else { |
no test coverage detected