Skip to content

Commit

Permalink
Refactor endpoints, update JSON
Browse files Browse the repository at this point in the history
  • Loading branch information
joepio committed Jan 3, 2023
1 parent 431a7f5 commit 6c322c8
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 37 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Changes to JS assets are not included here, but in [`atomic-data-browser`'s CHAN

## UNRELEASED

- New sign up / register flow. Add `/register` Endpoint #489 #254
- New sign up / register flow. Add `/register`, `/confirm-email`, `/add-public-key` endpoints #489 #254
- Add multi-tenancy support. Users can create their own `Drives` on subdomains. #288
- Refactor URLs. `store.self_url()` returns an `AtomicUrl`, which provides methods to easily add paths, find subdomains and more.
- Add support for subdomains, use a Wildcard TLS certificate #502
Expand Down
18 changes: 12 additions & 6 deletions lib/defaults/default_base_models.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,23 @@
},
{
"@id": "https://atomicdata.dev/classes/Property",
"https://atomicdata.dev/properties/description": "A Resource that should redirect the browser to a new location. It can also set a `redirectAgent`, which is used in Invites to create an Agent Resource on the Server from a Public Key that the user posesses. See the [Invite docs](https://docs.atomicdata.dev/invitations.html).",
"https://atomicdata.dev/properties/description": "A Property is a single field in a Class. It's the thing that a property field in an Atom points to. An example is `birthdate`. An instance of Property requires various Properties, most notably a `datatype` (e.g. `string` or `integer`), a human readable `description` (such as the thing you're reading), and a `shortname`.",
"https://atomicdata.dev/properties/isA": [
"https://atomicdata.dev/classes/Class"
],
"https://atomicdata.dev/properties/requires": [
"https://atomicdata.dev/properties/destination"
],
"https://atomicdata.dev/properties/parent": "https://atomicdata.dev/classes",
"https://atomicdata.dev/properties/recommends": [
"https://atomicdata.dev/properties/invite/redirectAgent"
"https://atomicdata.dev/properties/classtype",
"https://atomicdata.dev/properties/isDynamic",
"https://atomicdata.dev/properties/isLocked",
"https://atomicdata.dev/properties/allowsOnly"
],
"https://atomicdata.dev/properties/requires": [
"https://atomicdata.dev/properties/shortname",
"https://atomicdata.dev/properties/datatype",
"https://atomicdata.dev/properties/description"
],
"https://atomicdata.dev/properties/shortname": "redirect"
"https://atomicdata.dev/properties/shortname": "property"
},
{
"@id": "https://atomicdata.dev/classes/Class",
Expand Down
14 changes: 11 additions & 3 deletions lib/defaults/default_store.json
Original file line number Diff line number Diff line change
Expand Up @@ -749,10 +749,9 @@
"https://atomicdata.dev/properties/isA": [
"https://atomicdata.dev/classes/Property"
],
"https://atomicdata.dev/properties/lastCommit": "https://atomicdata.dev/commits/VB3gtWMkysTX5hKjbYjIM1hfVGPywT3pEPL8c7NwaUAJID6RzptGRPzmix8aKKDeb8Pj1WFv0UPV0YVPxcduBg==",
"https://atomicdata.dev/properties/parent": "https://atomicdata.dev/properties",
"https://atomicdata.dev/properties/shortname": "sub-resources"
},
},´
{
"@id": "https://atomicdata.dev/properties/tags",
"https://atomicdata.dev/properties/classtype": "https://atomicdata.dev/classes/Tag",
Expand All @@ -761,10 +760,19 @@
"https://atomicdata.dev/properties/isA": [
"https://atomicdata.dev/classes/Property"
],
"https://atomicdata.dev/properties/lastCommit": "https://atomicdata.dev/commits/fS0krtm1wDk0lodH0psnUKmBHBMKLuxnjkd7E7QbkzDk/irQ43gNW3lWxkwQj58ZNg6rUAUMDGJrLy1X3cHwBQ==",
"https://atomicdata.dev/properties/parent": "https://atomicdata.dev/properties",
"https://atomicdata.dev/properties/shortname": "tags"
},
{
"@id": "https://atomicdata.dev/properties/token",
"https://atomicdata.dev/properties/datatype": "https://atomicdata.dev/datatypes/string",
"https://atomicdata.dev/properties/description": "A server-generated string that should not mean anything to the client. It could be a JWT token, or something else.",
"https://atomicdata.dev/properties/isA": [
"https://atomicdata.dev/classes/Property"
],
"https://atomicdata.dev/properties/parent": "https://atomicdata.dev/properties",
"https://atomicdata.dev/properties/shortname": "token"
},
{
"@id": "https://atomicdata.dev/properties/write",
"https://atomicdata.dev/properties/classtype": "https://atomicdata.dev/classes/Agent",
Expand Down
3 changes: 2 additions & 1 deletion lib/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ use crate::{
commit::CommitResponse,
db::{query_index::NO_VALUE, val_prop_sub_index::find_in_val_prop_sub_index},
email::{self, MailMessage},
endpoints::{default_endpoints, Endpoint},
endpoints::Endpoint,
errors::{AtomicError, AtomicResult},
plugins::default_endpoints,
query::QueryResult,
resources::PropVals,
storelike::Storelike,
Expand Down
16 changes: 1 addition & 15 deletions lib/src/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Examples of endpoints are versions for resources, or (pages for) collections.
//! See https://docs.atomicdata.dev/endpoints.html or https://atomicdata.dev/classes/Endpoint
use crate::{errors::AtomicResult, plugins, urls, Db, Resource, Storelike, Value};
use crate::{errors::AtomicResult, urls, Db, Resource, Storelike, Value};

/// The function that is called when the request matches the path
type HandleFunction =
Expand Down Expand Up @@ -54,17 +54,3 @@ impl std::fmt::Debug for Endpoint {
.finish()
}
}

pub fn default_endpoints() -> Vec<Endpoint> {
vec![
plugins::versioning::version_endpoint(),
plugins::versioning::all_versions_endpoint(),
plugins::path::path_endpoint(),
plugins::search::search_endpoint(),
plugins::files::upload_endpoint(),
plugins::register::register_endpoint(),
plugins::register::confirm_email_endpoint(),
#[cfg(feature = "html")]
plugins::bookmark::bookmark_endpoint(),
]
}
15 changes: 10 additions & 5 deletions lib/src/plugins/reset_pubkey.rs → lib/src/plugins/add_pubkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ pub fn handle_request_email_pubkey(
) -> AtomicResult<Resource> {
let mut email_option: Option<EmailAddress> = None;
for (k, v) in url.query_pairs() {
match k.as_ref() {
"email" => email_option = Some(EmailAddress::new(v.to_string())?),
_ => {}
if let "email" = k.as_ref() {
email_option = Some(EmailAddress::new(v.to_string())?)
}
}
// by default just return the Endpoint
Expand All @@ -57,7 +56,12 @@ pub fn handle_request_email_pubkey(
};

// Find the agent by their email
let agent = Agent::from_email(&email.to_string(), store)?;
let agent = match Agent::from_email(&email.to_string(), store) {
Ok(a) => a,
// If we can't find the agent, we should still return a `success` response,
// in order to prevent users to know that the email exists.
Err(_) => return return_success(),
};

// send the user an e-mail to confirm sign up
let store_clone = store.clone();
Expand Down Expand Up @@ -108,12 +112,13 @@ pub fn handle_confirm_add_pubkey(
_ => {}
}
}
let pubkey = pubkey_option.ok_or("No public-key provided")?;

let Some(token) = token_opt else {
return confirm_add_pubkey().to_resource(store);
};

let pubkey = pubkey_option.ok_or("No public-key provided")?;

// Parse and verify the JWT token
let confirmation = crate::token::verify_claim::<AddPubkeyToken>(store, &token)?.custom;

Expand Down
29 changes: 24 additions & 5 deletions lib/src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Plugins can have functions that are called at specific moments by Atomic-Server.
For example:
- Before returning a Resource. These are either Endpoints or Class Extenders.
- Before returning a Resource. These are either [Endpoint]s or Class Extenders.
- Before applying a Commit.
In the long term, these plugins will probably be powered by WASM and can be extended at runtime.
Expand All @@ -16,13 +16,13 @@ However, they are designed in such a way that they have a limited scope and a cl
## Extending resources
There are two ways of extending / modifying a Resource.
Endpoints are great for APIs that have a fixed route, and Class Extenders are great for APIs that don't have a fixed route.
[Endpoint]s are great for APIs that have a fixed route, and Class Extenders are great for APIs that don't have a fixed route.
Endpoints are easier to generate from Rust, and will be available the second a server is Running.
### Endpoints
### [Endpoint]s
Resources that typically parse query parameters and return a dynamic resource.
When adding an endpoint, add it to the list of endpoints in [lib/src/endpoints.rs]
When adding an endpoint, add it to the list of [default_endpoints] in this file.
Endpoints are all instances of the [crate] class.
They are presented in the UI as a form.
Expand All @@ -31,22 +31,41 @@ They are presented in the UI as a form.
Similar to Endpoints, Class Extenders can modify their contents before creating a response.
Contrary to Endpoints, these can be any type of Class.
They are used for performing custom queries, or calculating dynamic attributes.
Add these by registering the handler at [crate::db::Db::get_resource_extended].
*/

use crate::endpoints::Endpoint;

// Class Extenders
pub mod chatroom;
pub mod importer;
pub mod invite;

// Endpoints
pub mod add_pubkey;
#[cfg(feature = "html")]
pub mod bookmark;
pub mod files;
pub mod path;
pub mod register;
pub mod reset_pubkey;
pub mod search;
pub mod versioning;

// Utilities / helpers
mod utils;

pub fn default_endpoints() -> Vec<Endpoint> {
vec![
versioning::version_endpoint(),
versioning::all_versions_endpoint(),
path::path_endpoint(),
search::search_endpoint(),
files::upload_endpoint(),
register::register_endpoint(),
register::confirm_email_endpoint(),
add_pubkey::request_email_add_pubkey(),
add_pubkey::confirm_add_pubkey(),
#[cfg(feature = "html")]
bookmark::bookmark_endpoint(),
]
}
1 change: 1 addition & 0 deletions lib/src/plugins/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pub fn handle_register_name_and_email(
.get_server_url()
.clone()
.set_path(urls::PATH_CONFIRM_EMAIL)
// .set_subdomain(Some(&name.to_string()))?
.url();
confirm_url.set_query(Some(&format!("token={}", token)));
let message = MailMessage {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/populate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ pub fn populate_collections(store: &impl Storelike) -> AtomicResult<()> {
pub fn populate_endpoints(store: &crate::Db) -> AtomicResult<()> {
use crate::atomic_url::Routes;

let endpoints = crate::endpoints::default_endpoints();
let endpoints = crate::plugins::default_endpoints();
let endpoints_collection = store.get_server_url().set_route(Routes::Endpoints);
for endpoint in endpoints {
let mut resource = endpoint.to_resource(store)?;
Expand Down

0 comments on commit 6c322c8

Please sign in to comment.