Restrict access to trash, only admin

First of all you have to deny access to trash page in admin. To show trash, the 'post_status' argument for main query must be ‘trash’, so you can check that and redirect if current user is not an administrator:

add_action( 'pre_get_posts', 'deny_trash_access' );

function deny_trash_access( $query ) {
  // nothing to do if not in admin or if user is an admin
  if (
    ! is_admin()
    || ! $query->is_main_query()
    || current_user_can( 'remove_users' )
  ) return; 
  $status = $query->get( 'post_status' );
  if (
    $status === 'trash'
    || ( is_array( $status ) && in_array( 'trash', $status, true ) )
  ) {
    wp_safe_redirect( admin_url() );
    exit();
  }
}

However, that not prevent users to restore or delete permanently posts.

That can be done using ‘wp_insert_post_data’ filter, and if in current post data the post status is “trash”, and a user try to change it, you can abort the editing by forcing 'post_status' to be “trash”:

add_filter( 'wp_insert_post_data', 'prevent_trash_status_change', 999, 2 );

function prevent_trash_status_change( $data, $postarr ) {
  if ( ! isset( $postarr['ID'] ) || empty( $postarr['ID'] ) ) return $data;
  if ( current_user_can( 'remove_users' ) ) return $data; // admin can edit trash
  // get the post how it is before the update
  $old = get_post( $postarr[ID] );
  // if post is trashed, force to be trashed also after the update
  if ( $old->post_status === 'draft' ) { 
    $data['post_status'] = 'draft';
  } 
  return $data;
}

Put this 2 code snippets in your function.php or in a plugin file and you are done.