Skip to content

Commit

Permalink
add endpoint to retrieve other user ssh keys
Browse files Browse the repository at this point in the history
  • Loading branch information
xerbalind committed Jun 2, 2024
1 parent c1699dc commit b7b875b
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 14 deletions.
55 changes: 41 additions & 14 deletions src/controllers/users_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub async fn show_user<'r>(
html: template!("users/show.html";
user: User = user.clone(),
current_user: User = session.user,
errors: Option<ValidationErrors> = None
),
json: Json(user),
})
Expand All @@ -58,6 +59,24 @@ pub async fn show_user<'r>(
}
}

#[get("/users/keys/<username>")]
pub async fn show_ssh_key<'r>(
db: DbConn,
username: String,
) -> Json<Vec<String>> {
let user = User::find_by_username(username, &db).await.unwrap();
let mut keys = vec![];
if let Some(ssh_keys) = user.ssh_key {
for line in ssh_keys.lines() {
let line = line.trim();
if !line.is_empty() {
keys.push(line.to_string())
}
}
}
Json(keys)
}

#[get("/users")]
pub async fn list_users<'r>(
session: AdminSession,
Expand Down Expand Up @@ -184,27 +203,35 @@ pub async fn register<'r>(
}

#[put("/users/<username>", data = "<change>")]
pub async fn update_user<'r>(
pub async fn update_user<'r, 'o: 'r>(
username: String,
change: Api<UserChange>,
session: UserSession,
db: DbConn,
) -> Result<
Either<
impl Responder<'r, 'static>,
Custom<impl Debug + Responder<'r, 'static>>,
>,
> {
) -> Result<impl Responder<'r, 'o>> {
let mut user = User::find_by_username(username, &db).await?;
if session.user.id == user.id || session.user.admin {
user.change_with(change.into_inner())?;
let user = user.update(&db).await?;
Ok(Left(Accepter {
html: Redirect::to(uri!(show_user(user.username))),
json: Custom(Status::NoContent, ()),
}))
match user.change_with(change.into_inner()) {
Ok(()) => {
let user = user.update(&db).await?;
Ok(OneOf::One(Accepter {
html: Redirect::to(uri!(show_user(user.username))),
json: Custom(Status::NoContent, ()),
}))
},
Err(ZauthError::ValidationError(errors)) => Ok(OneOf::Two(Custom(
Status::UnprocessableEntity,
template! {
"users/show.html";
user: User = user,
current_user: User = session.user,
errors: Option<ValidationErrors> = Some(errors.clone()),
},
))),
Err(other) => Err(other),
}
} else {
Ok(Right(Custom(Status::Forbidden, ())))
Ok(OneOf::Three(Custom(Status::Forbidden, ())))
}
}

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ fn assemble(rocket: Rocket<Build>) -> Rocket<Build> {
users_controller::register,
users_controller::current_user,
users_controller::show_user,
users_controller::show_ssh_key,
users_controller::list_users,
users_controller::update_user,
users_controller::change_state,
Expand Down
1 change: 1 addition & 0 deletions src/models/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ impl User {
self.ssh_key = Some(ssh_key);
}
self.subscribed_to_mailing_list = change.subscribed_to_mailing_list;
self.validate()?;
Ok(())
}

Expand Down
9 changes: 9 additions & 0 deletions templates/users/show.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@

<div class="title">Update profile information</div>

<!-- Error messages -->
{% match errors %}
{% when Some with (errors) %}
<div class="notification is-danger is-light">
{{ errors }}
</div>
{% when None %}
{% endmatch %}

<form class="profile-edit-form" action="/users/{{ user.username }}" method="POST">
<input type="hidden" name="_method" value="put"/>

Expand Down
14 changes: 14 additions & 0 deletions tests/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,20 @@ async fn show_user_as_admin() {
#[rocket::async_test]
async fn update_self() {
common::as_user(async move |http_client, db, user| {
let response = http_client
.put(format!("/users/{}", user.username))
.header(ContentType::Form)
.header(Accept::JSON)
.body("ssh_key=ssh-fake%20supersecretkey")
.dispatch()
.await;

assert_eq!(
response.status(),
Status::UnprocessableEntity,
"user should not be able to update invalid public ssh key"
);

let response = http_client
.put(format!("/users/{}", user.username))
.header(ContentType::Form)
Expand Down

0 comments on commit b7b875b

Please sign in to comment.