This repository has been archived by the owner on Jul 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathlib.rs
143 lines (118 loc) · 4.24 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! # A GraphQL server written in Rust
#![forbid(unsafe_code)]
use anyhow::Result;
use axum::{
extract::Extension,
routing::{get, IntoMakeService},
Router, Server,
};
use graphql::create_schema;
use hyper::server::conn::AddrIncoming;
use oso::{Oso, PolarClass};
use router::{events_handler, graphiql, graphql_handler, health_handler};
use sea_orm::DatabaseConnection;
use std::sync::Arc;
use tower_http::trace::{self, TraceLayer};
use caster_auth::jwks::get_jwks;
use caster_domains::{
episodes::{
model::Episode,
service::{DefaultEpisodesService, EpisodesService},
AUTHORIZATION as EPISODES_AUTHZ,
},
profiles::{
model::Profile,
service::{DefaultProfilesService, ProfilesService},
AUTHORIZATION as PROFILES_AUTHZ,
},
role_grants::service::{DefaultRoleGrantsService, RoleGrantsService},
shows::{
model::Show,
service::{DefaultShowsService, ShowsService},
AUTHORIZATION as SHOWS_AUTHZ,
},
users::{
model::User,
service::{UsersService, UsersServiceTrait},
AUTHORIZATION as USERS_AUTHZ,
},
};
use caster_utils::config::Config;
use events::connections::Connections;
mod router;
/// GraphQL Schema Creation
pub mod graphql;
/// `WebSocket` Events
pub mod events;
/// Dependencies needed by the resolvers
pub struct Context {
/// The app config
pub config: &'static Config,
/// The database connections
pub db: Arc<DatabaseConnection>,
/// The `Oso` authorization library
pub oso: Oso,
/// The `User` entity service
pub users: Arc<dyn UsersServiceTrait>,
/// The `Profile` entity service
pub profiles: Arc<dyn ProfilesService>,
/// The `RoleGrant` entity service
pub role_grants: Arc<dyn RoleGrantsService>,
/// The `Show` entity service
pub shows: Arc<dyn ShowsService>,
/// The `Episode` entity service
pub episodes: Arc<dyn EpisodesService>,
/// WebSockets connections currently active on this server
pub connections: Connections,
}
/// Intialize dependencies
impl Context {
/// Create a new set of dependencies based on the given shared resources
pub async fn init(config: &'static Config) -> Result<Self> {
let db = Arc::new(sea_orm::Database::connect(&config.database.url).await?);
// Set up authorization
let mut oso = Oso::new();
let connections = Connections::default();
oso.register_class(User::get_polar_class_builder().name("User").build())?;
oso.register_class(Profile::get_polar_class_builder().name("Profile").build())?;
oso.register_class(Show::get_polar_class_builder().name("Show").build())?;
oso.register_class(Episode::get_polar_class_builder().name("Episode").build())?;
oso.load_str(&[USERS_AUTHZ, PROFILES_AUTHZ, SHOWS_AUTHZ, EPISODES_AUTHZ].join("\n"))?;
Ok(Self {
config,
users: Arc::new(UsersService::new(&db)),
profiles: Arc::new(DefaultProfilesService::new(&db)),
role_grants: Arc::new(DefaultRoleGrantsService::new(&db)),
shows: Arc::new(DefaultShowsService::new(&db)),
episodes: Arc::new(DefaultEpisodesService::new(&db)),
oso,
db,
connections,
})
}
}
/// Start the server and return the bound address and a `Future`.
pub async fn run(ctx: Arc<Context>) -> Result<Server<AddrIncoming, IntoMakeService<Router>>> {
let port = ctx.config.port;
let jwks = get_jwks(ctx.config).await;
let schema = create_schema(ctx.clone())?;
let app = Router::new()
.route("/health", get(health_handler))
.route("/graphql", get(graphiql).post(graphql_handler))
.route("/events", get(events_handler))
.layer(
TraceLayer::new_for_http()
.make_span_with(trace::DefaultMakeSpan::new().level(tracing::Level::INFO))
.on_response(trace::DefaultOnResponse::new().level(tracing::Level::INFO)),
)
.layer(Extension(jwks))
.layer(Extension(ctx))
.layer(Extension(schema));
let server = Server::bind(
&format!("0.0.0.0:{}", port)
.parse()
.expect("Unable to parse bind address"),
)
.serve(app.into_make_service());
Ok(server)
}