mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-04-30 23:21:19 -04:00
support username properly in POST /api/users/:id
I mistakenly left this out. Also, fix the behavior if something is forgotten. Before, it'd silently ignore it. Now, it correctly returns Unimplemented, in both POST /api/users/:id and PUT /api/users.
This commit is contained in:
parent
6c90077ff1
commit
163eaa4cf9
@ -516,14 +516,16 @@ pub struct ToplevelUser {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct PostUser<'a> {
|
pub struct PostUser<'a> {
|
||||||
pub csrf: Option<&'a str>,
|
pub csrf: Option<&'a str>,
|
||||||
pub update: Option<UserSubset<'a>>,
|
pub update: Option<UserSubset<'a>>,
|
||||||
pub precondition: Option<UserSubset<'a>>,
|
pub precondition: Option<UserSubset<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct UserSubset<'a> {
|
pub struct UserSubset<'a> {
|
||||||
#[serde(borrow)]
|
#[serde(borrow)]
|
||||||
pub username: Option<&'a str>,
|
pub username: Option<&'a str>,
|
||||||
@ -551,7 +553,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// API/config analog of `Permissions` defined in `db/proto/schema.proto`.
|
/// API/config analog of `Permissions` defined in `db/proto/schema.proto`.
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Permissions {
|
pub struct Permissions {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -44,20 +44,25 @@ impl Service {
|
|||||||
bail_t!(Unauthenticated, "must have admin_users permission");
|
bail_t!(Unauthenticated, "must have admin_users permission");
|
||||||
}
|
}
|
||||||
let r = extract_json_body(&mut req).await?;
|
let r = extract_json_body(&mut req).await?;
|
||||||
let r: json::UserSubset = serde_json::from_slice(&r).map_err(|e| bad_req(e.to_string()))?;
|
let mut r: json::UserSubset =
|
||||||
|
serde_json::from_slice(&r).map_err(|e| bad_req(e.to_string()))?;
|
||||||
let username = r
|
let username = r
|
||||||
.username
|
.username
|
||||||
|
.take()
|
||||||
.ok_or_else(|| format_err_t!(InvalidArgument, "username must be specified"))?;
|
.ok_or_else(|| format_err_t!(InvalidArgument, "username must be specified"))?;
|
||||||
let mut change = db::UserChange::add_user(username.to_owned());
|
let mut change = db::UserChange::add_user(username.to_owned());
|
||||||
if let Some(Some(pwd)) = r.password {
|
if let Some(Some(pwd)) = r.password.take() {
|
||||||
change.set_password(pwd.to_owned());
|
change.set_password(pwd.to_owned());
|
||||||
}
|
}
|
||||||
if let Some(preferences) = r.preferences {
|
if let Some(preferences) = r.preferences.take() {
|
||||||
change.config.preferences = preferences;
|
change.config.preferences = preferences;
|
||||||
}
|
}
|
||||||
if let Some(ref permissions) = r.permissions {
|
if let Some(ref permissions) = r.permissions.take() {
|
||||||
change.permissions = permissions.into();
|
change.permissions = permissions.into();
|
||||||
}
|
}
|
||||||
|
if r != Default::default() {
|
||||||
|
bail_t!(Unimplemented, "unsupported user fields: {:#?}", r);
|
||||||
|
}
|
||||||
let mut l = self.db.lock();
|
let mut l = self.db.lock();
|
||||||
let user = l.apply_user_change(change)?;
|
let user = l.apply_user_change(change)?;
|
||||||
serve_json(&req, &PutUsersResponse { id: user.id })
|
serve_json(&req, &PutUsersResponse { id: user.id })
|
||||||
@ -145,33 +150,54 @@ impl Service {
|
|||||||
}
|
}
|
||||||
(_, _) => {}
|
(_, _) => {}
|
||||||
}
|
}
|
||||||
if let Some(ref precondition) = r.precondition {
|
if let Some(mut precondition) = r.precondition {
|
||||||
if matches!(precondition.preferences, Some(ref p) if p != &user.config.preferences) {
|
if matches!(precondition.username.take(), Some(n) if n != &user.username) {
|
||||||
|
bail_t!(FailedPrecondition, "username mismatch");
|
||||||
|
}
|
||||||
|
if matches!(precondition.preferences.take(), Some(ref p) if p != &user.config.preferences)
|
||||||
|
{
|
||||||
bail_t!(FailedPrecondition, "preferences mismatch");
|
bail_t!(FailedPrecondition, "preferences mismatch");
|
||||||
}
|
}
|
||||||
if let Some(p) = precondition.password {
|
if let Some(p) = precondition.password.take() {
|
||||||
if !user.check_password(p)? {
|
if !user.check_password(p)? {
|
||||||
bail_t!(FailedPrecondition, "password mismatch"); // or Unauthenticated?
|
bail_t!(FailedPrecondition, "password mismatch"); // or Unauthenticated?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ref p) = precondition.permissions {
|
if let Some(p) = precondition.permissions.take() {
|
||||||
if user.permissions != db::Permissions::from(p) {
|
if user.permissions != db::Permissions::from(&p) {
|
||||||
bail_t!(FailedPrecondition, "permissions mismatch");
|
bail_t!(FailedPrecondition, "permissions mismatch");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safety valve in case something is added to UserSubset and forgotten here.
|
||||||
|
if precondition != Default::default() {
|
||||||
|
bail_t!(
|
||||||
|
Unimplemented,
|
||||||
|
"preconditions not supported: {:#?}",
|
||||||
|
&precondition
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if let Some(update) = r.update {
|
}
|
||||||
|
if let Some(mut update) = r.update {
|
||||||
let mut change = user.change();
|
let mut change = user.change();
|
||||||
if let Some(preferences) = update.preferences {
|
if let Some(n) = update.username.take() {
|
||||||
|
change.username = n.to_string();
|
||||||
|
}
|
||||||
|
if let Some(preferences) = update.preferences.take() {
|
||||||
change.config.preferences = preferences;
|
change.config.preferences = preferences;
|
||||||
}
|
}
|
||||||
match update.password {
|
match update.password.take() {
|
||||||
None => {}
|
None => {}
|
||||||
Some(None) => change.clear_password(),
|
Some(None) => change.clear_password(),
|
||||||
Some(Some(p)) => change.set_password(p.to_owned()),
|
Some(Some(p)) => change.set_password(p.to_owned()),
|
||||||
}
|
}
|
||||||
if let Some(ref permissions) = update.permissions {
|
if let Some(permissions) = update.permissions.take() {
|
||||||
change.permissions = permissions.into();
|
change.permissions = (&permissions).into();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safety valve in case something is added to UserSubset and forgotten here.
|
||||||
|
if update != Default::default() {
|
||||||
|
bail_t!(Unimplemented, "updates not supported: {:#?}", &update);
|
||||||
}
|
}
|
||||||
db.apply_user_change(change)?;
|
db.apply_user_change(change)?;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user