restapi/
lib.rs

1//! # Rust Rest API Stack with User Management, Kafka Message Publishing, S3 uploads/downloads, and Prometheus for Monitoring
2//!
3//! A secure-by-default Rest API using [hyper](https://crates.io/crates/hyper), [tokio](https://crates.io/crates/tokio), [bb8](https://crates.io/crates/bb8), [kafka-threadpool](https://crates.io/crates/kafka-threadpool), postgres, and [prometheus](https://crates.io/crates/prometheus) for monitoring.
4//!
5//! ## Features
6//!
7//! 1.  User management and authentication stored in postgres
8//! 1.  Async s3 uploading and downloading (to/from local files or to/from memory)
9//! 1.  Decoupled, async kafka threadpool that uses environment variables to connect to a kafka cluster with client mtls for authentication and encryption in transit
10//! 1.  Async publishing for all successful user events to a kafka topic (topic default: ``user.events``) and partition key (key default: ``user-{user.id}``)
11//! 1.  Async kafka messaging for one-off messages using custom kafka topic(s), partition key(s) and custom header(s).
12//!
13//! ## Examples
14//!
15//! Please see the [restapi/examples/server.rs](https://github.com/jay-johnson/restapi/blob/main/examples/server.rs) for developing your own rest api.
16//!
17//! ## Overview
18//!
19//! ### User
20//!
21//! - User password reset and user email change support using one-time-use tokens that are stored in postgres.
22//! - Users can upload and manage files stored on AWS S3 (assuming valid credentials are loaded outside this rust project).
23//! - User passwords are hashed using [argon2](https://docs.rs/argon2/latest/argon2/).
24//!
25//! ### Auth
26//!
27//! - User authentication enabled by default
28//! - Default JWT signing keys included with [documentation for building new keys as needed](https://github.com/jay-johnson/restapi/tree/main/jwt).
29//!
30//! ### Database
31//!
32//! - The rest api server utilizes postgres with a [bb8 client threadpool](https://github.com/djc/bb8).
33//! - The postgres database requires each client connection include the postgres tls certificate authority file for encrypting data in-transit.
34//! - Includes [pg4admin](https://www.pgadmin.org/docs/pgadmin4/latest/index.html) for database management in a browser (deployed with docker compose).
35//!
36//! ### TLS Encryption
37//!
38//! - Includes a tls asset generator tool ([./tls/create-tls-assets.sh](https://github.com/jay-johnson/restapi/blob/main/tls/create-tls-assets.sh)) for building self-signed tls assets including your own private Certificate Authority (CA).
39//!
40//! #### Ingress
41//!
42//! Component        | Status
43//! ---------------- | ------
44//! Rest API Server  | Listening for encrypted client connections on tcp port **3000**
45//! Postgres         | Listening for encrypted client connections on tcp port **5432** (tls Certificate Authority required)
46//! pgAdmin          | Listening for encrypted HTTP client connections on tcp port **5433**
47//!
48//! ## Getting Started
49//!
50//! ### Clone the repo
51//!
52//! ```bash
53//! git clone https://github.com/jay-johnson/restapi
54//! cd restapi
55//! ```
56//!
57//! ### Generate TLS Assets and a Private Certificate Authority (CA) using CFSSL
58//!
59//! Generate new tls assets under the ``./tls`` directory with these commands:
60//!
61//! ```bash
62//! cd tls
63//! ./create-tls-assets.sh
64//! cd ..
65//! ```
66//!
67//! Please refer to the [Generating TLS Assets with CFSSL](./tls/README.md) for more information.
68//!
69//! ### Generate JWT Private and Public Signing Keys
70//!
71//! Generate new signing JWT keys under the ``./jwt`` directory with these commands:
72//!
73//! ```bash
74//! cd jwt
75//! ./recreate-jwt.sh
76//! cd ..
77//! ```
78//!
79//! Please refer to the [How to build JWT private and public keys for the jsonwebtokens crate doc](./jwt/README.md) for more information.
80//!
81//! ### Deploy Postgres and pgAdmin using Podman
82//!
83//! Please refer to the [Build and Deploy a Secured Postgres backend doc](./docker/db/README.md) for more information.
84//!
85//! ### Build API Server
86//!
87//! ```bash
88//! cargo build --example server
89//! ```
90//!
91//! ### Run API Server
92//!
93//! ```bash
94//! export RUST_BACKTRACE=1 && export RUST_LOG=info,kafka_threadpool=info && ./target/debug/examples/server
95//! ```
96//!
97//! ## Environment Variables
98//!
99//! ### Rest API
100//!
101//! Environment Variable  | Default
102//! --------------------- | -------
103//! SERVER_NAME_API       | api
104//! SERVER_NAME_LABEL     | rust-restapi
105//! API_ENDPOINT          | 0.0.0.0:3000
106//! API_TLS_DIR           | ./tls/api
107//! API_TLS_CA            | ./tls/ca/ca.pem
108//! API_TLS_CERT          | ./tls/api/server.pem
109//! API_TLS_KEY           | ./tls/api/server-key.pem
110//!
111//! ### User Email Verification
112//!
113//! Environment Variable                   | Default
114//! -------------------------------------- | -------
115//! USER_EMAIL_VERIFICATION_REQUIRED       | "0"
116//! USER_EMAIL_VERIFICATION_ENABLED        | "1"
117//! USER_EMAIL_VERIFICATION_EXP_IN_SECONDS | "2592000"
118//!
119//! ### User One-Time-Use Token Expiration for Password Recovery
120//!
121//! Environment Variable    | Default
122//! ----------------------- | -------
123//! USER_OTP_EXP_IN_SECONDS | "2592000"
124//!
125//! ### Postgres Database
126//!
127//! Environment Variable  | Default
128//! --------------------- | -------
129//! DB_NAME               | mydb
130//! POSTGRES_USERNAME     | datawriter
131//! POSTGRES_PASSWORD     | "123321"
132//! POSTGRES_ENDPOINT     | 0.0.0.0:5432
133//! POSTGRES_TLS_DIR      | ./tls/postgres
134//! POSTGRES_TLS_CA       | ./tls/ca/ca.pem
135//! POSTGRES_TLS_CERT     | ./tls/postgres/client.pem
136//! POSTGRES_TLS_KEY      | ./tls/postgres/client-key.pem
137//! POSTGRES_DB_CONN_TYPE | postgresql
138//!
139//! ### Kafka Cluster
140//!
141//! Please refer to the [kafka_threadpool docs](https://crates.io/crates/kafka-threadpool) for more information.
142//!
143//! Environment Variable             | Purpose / Value
144//! -------------------------------- | ---------------
145//! KAFKA_PUBLISH_EVENTS             | if set to ``true`` or ``1`` publish all user events to kafka
146//! KAFKA_ENABLED                    | toggle the kafka_threadpool on with: ``true`` or ``1`` anything else disables the threadpool
147//! KAFKA_LOG_LABEL                  | tracking label that shows up in all crate logs
148//! KAFKA_BROKERS                    | comma-delimited list of brokers (``host1:port,host2:port,host3:port``)
149//! KAFKA_TOPICS                     | comma-delimited list of supported topics
150//! KAFKA_PUBLISH_RETRY_INTERVAL_SEC | number of seconds to sleep before each publish retry
151//! KAFKA_PUBLISH_IDLE_INTERVAL_SEC  | number of seconds to sleep if there are no message to process
152//! KAFKA_NUM_THREADS                | number of threads for the threadpool
153//! KAFKA_TLS_CLIENT_KEY             | optional - path to the kafka mTLS key (./tls/kafka-cluster-0/client-key.pem)
154//! KAFKA_TLS_CLIENT_CERT            | optional - path to the kafka mTLS certificate (./tls/kafka-cluster-0/client.pem)
155//! KAFKA_TLS_CLIENT_CA              | optional - path to the kafka mTLS certificate authority (CA) (./tls/ca/ca.pem)
156//! KAFKA_METADATA_COUNT_MSG_OFFSETS | optional - set to anything but ``true`` to bypass counting the offsets
157//!
158//! #### Sample kafka.env file
159//!
160//! ```bash
161//! # enable the cluster
162//! export KAFKA_ENABLED=1
163//! export KAFKA_LOG_LABEL="ktp"
164//! export KAFKA_BROKERS="host1:port,host2:port,host3:port"
165//! export KAFKA_TOPICS="testing"
166//! export KAFKA_PUBLISH_RETRY_INTERVAL_SEC="1.0"
167//! export KAFKA_NUM_THREADS="5"
168//! export KAFKA_TLS_CLIENT_CA="./tls/ca/ca.pem"
169//! export KAFKA_TLS_CLIENT_CERT="./tls/kafka-cluster-0/client.pem"
170//! export KAFKA_TLS_CLIENT_KEY="./tls/kafka-cluster-0/client-key.pem"
171//! # the KafkaPublisher can count the offsets for each topic with "true" or "1"
172//! export KAFKA_METADATA_COUNT_MSG_OFFSETS="true"
173//! ```
174//!
175//! ### S3
176//!
177//! Environment Variable | Default
178//! -------------------- | -------
179//! S3_DATA_BUCKET       | YOUR_BUCKET
180//! S3_DATA_PREFIX       | /rust-restapi/tests
181//! S3_STORAGE_CLASS     | STANDARD
182//! S3_DATA_UPLOAD_TO_S3 | "0"
183//!
184//! ### JWT
185//!
186//! Environment Variable                 | Default
187//! ------------------------------------ | -------
188//! TOKEN_EXPIRATION_SECONDS_INTO_FUTURE | "2592000"
189//! TOKEN_ORG                            | example.org
190//! TOKEN_HEADER                         | Bearer
191//! TOKEN_ALGO_PRIVATE_KEY               | ./jwt/private-key-pkcs8.pem
192//! TOKEN_ALGO_PUBLIC_KEY                | ./jwt/public-key.pem
193//! SERVER_PKI_DIR_JWT                   | ./jwt
194//! SERVER_PASSWORD_SALT                 | 78197b60-c950-4339-a52c-053165a04764
195//!
196//! ### Rust
197//!
198//! Environment Variable | Default
199//! -------------------- | -------
200//! RUST_BACKTRACE       | "1"
201//! RUST_LOG             | info
202//!
203//! ### Debug
204//!
205//! Environment Variable | Default
206//! -------------------- | -------
207//! DEBUG                | "1"
208//!
209//! ## Docker Builds
210//!
211//! ### Build Base Image
212//!
213//! This will build an initial base image using podman. Note: this base image will **not** work on a different cpu chipset because the openssl libraries are compiled within the image for this base image.
214//!
215//! ```bash
216//! ./build-base.sh
217//! ```
218//!
219//! ### Build Derived Image
220//!
221//! By reusing the base image, this derived image only needs to recompile the server. With minimal code changes, this is a much faster build than the base image build.
222//!
223//! ```bash
224//! ./build-derived.sh
225//! ```
226//!
227//! ## Kubernetes
228//!
229//! ### Start Kafka
230//!
231//! If you do not have a running Kafka cluster, you can deploy your own with:
232//!
233//! https://github.com/jay-johnson/rust-with-strimzi-kafka-and-tls
234//!
235//! ### Helm Chart
236//!
237//! #### Deploy TLS Assets into Kubernetes
238//!
239//! This command will deploy all jwt keys, tls assets and credentials into the ``dev`` namespace:
240//!
241//! ```bash
242//! ./deploy-kubernetes-assets.sh -e dev
243//! ```
244//!
245//! #### Deploy the Rust Rest API into Kubernetes
246//!
247//! Please refer to the [Deploying the Rust Rest API helm chart into kubernetes guide](https://github.com/jay-johnson/restapi/blob/main/charts/rust-restapi/README.md) for deploying the example helm chart into a kubernetes cluster.
248//!
249//! By default this uses the ``jayjohnson/rust-restapi`` container image
250//!
251//! ```bash
252//! helm upgrade --install -n dev dev-api ./charts/rust-restapi -f ./charts/rust-restapi/values.yaml
253//! ```
254//!
255//! ## Monitoring
256//!
257//! ### Prometheus
258//!
259//! This section assumes you have a working prometheus instance already running inside kubernetes. Below is the Prometheus ``scrape_config`` to monitor the rest api deployment replica(s) within kubernetes. Note this config also assumes the api chart is running in the ``dev`` namespace:
260//!
261//! ```yaml
262//! scrape_configs:
263//! - job_name: rust-restapi
264//!   scrape_interval: 10s
265//!   scrape_timeout: 5s
266//!   metrics_path: /metrics
267//!   scheme: https
268//!   tls_config:
269//!     insecure_skip_verify: true
270//!   static_configs:
271//!   - targets:
272//!     - dev-api.dev.svc.cluster.local:3000
273//! ```
274//!
275//! ## Supported APIs
276//!
277//! Here are the supported json contracts for each ``Request`` and ``Response`` based off the url. Each client request is handled by the [`handle_requests`](crate::handle_request::handle_request) and returned as a response back to the client (serialization using ``serde_json``)
278//!
279//! ### User APIs
280//!
281//! #### Create User
282//!
283//! Create a single ``users`` record for the new user
284//!
285//! - URL path: ``/user``
286//! - Method: ``POST``
287//! - Handler: [`create_user`](crate::requests::user::create_user::create_user)
288//! - Request: [`ApiReqUserCreate`](crate::requests::user::create_user::ApiReqUserCreate)
289//! - Response: [`ApiResUserCreate`](crate::requests::user::create_user::ApiResUserCreate)
290//!
291//! #### Update User
292//!
293//! Update supported ``users`` fields (including change user email and password)
294//!
295//! - URL path: ``/user``
296//! - Method: ``PUT``
297//! - Handler: [`update_user`](crate::requests::user::update_user::update_user)
298//! - Request: [`ApiReqUserUpdate`](crate::requests::user::update_user::ApiReqUserUpdate)
299//! - Response: [`ApiResUserUpdate`](crate::requests::user::update_user::ApiResUserUpdate)
300//!
301//! #### Get User
302//!
303//! Get a single user by ``users.id`` - by default, a user can only get their own account details
304//!
305//! - URL path: ``/user/USERID``
306//! - Method: ``GET``
307//! - Handler: [`get_user`](crate::requests::user::get_user::get_user)
308//! - Request: [`ApiReqUserGet`](crate::requests::user::get_user::ApiReqUserGet)
309//! - Response: [`ApiResUserGet`](crate::requests::user::get_user::ApiResUserGet)
310//!
311//! #### Delete User
312//!
313//! Delete a single ``users`` record (note: this does not delete the db record, just sets the ``users.state`` to inactive ``1``)
314//!
315//! - URL path: ``/user``
316//! - Method: ``DELETE``
317//! - Handler: [`delete_user`](crate::requests::user::delete_user::delete_user)
318//! - Request: [`ApiReqUserDelete`](crate::requests::user::delete_user::ApiReqUserDelete)
319//! - Response: [`ApiResUserDelete`](crate::requests::user::delete_user::ApiResUserDelete)
320//!
321//! #### Search Users in the db
322//!
323//! Search for matching ``users`` records in the db
324//!
325//! - URL path: ``/user/search``
326//! - Method: ``POST``
327//! - Handler: [`search_users`](crate::requests::user::search_users::search_users)
328//! - Request: [`ApiReqUserSearch`](crate::requests::user::search_users::ApiReqUserSearch)
329//! - Response: [`ApiResUserSearch`](crate::requests::user::search_users::ApiResUserSearch)
330//!
331//! #### Create One-Time-Use Password Reset Token (OTP)
332//!
333//! Create a one-time-use password reset token that allows a user to change their ``users.password`` value by presenting the token
334//!
335//! - URL path: ``/user/password/reset``
336//! - Method: ``POST``
337//! - Handler: [`create_otp`](crate::requests::user::create_otp::create_otp)
338//! - Request: [`ApiReqUserCreateOtp`](crate::requests::user::create_otp::ApiReqUserCreateOtp)
339//! - Response: [`ApiResUserCreateOtp`](crate::requests::user::create_otp::ApiResUserCreateOtp)
340//!
341//! #### Consume a One-Time-Use Password Reset Token (OTP)
342//!
343//! Consume a one-time-use password and change the user's ``users.password`` value to the new argon2-hashed password
344//!
345//! - URL path: ``/user/password/change``
346//! - Method: ``POST``
347//! - Handler: [`consume_user_otp`](crate::requests::user::consume_user_otp::consume_user_otp)
348//! - Request: [`ApiReqUserConsumeOtp`](crate::requests::user::consume_user_otp::ApiReqUserConsumeOtp)
349//! - Response: [`ApiResUserConsumeOtp`](crate::requests::user::consume_user_otp::ApiResUserConsumeOtp)
350//!
351//! #### Verify a User's email
352//!
353//! Consume a one-time-use verification token and change the user's ``users.verified`` value verified (``1``)
354//!
355//! - URL path: ``/user/verify``
356//! - Method: ``GET``
357//! - Handler: [`verify_user`](crate::requests::user::verify_user::verify_user)
358//! - Request: [`ApiReqUserVerify`](crate::requests::user::verify_user::ApiReqUserVerify)
359//! - Response: [`ApiResUserVerify`](crate::requests::user::verify_user::ApiResUserVerify)
360//!
361//! ### User S3 APIs
362//!
363//! #### Upload a file asynchronously to AWS S3 and store a tracking record in the db
364//!
365//! Upload a local file on disk to AWS S3 asynchronously and store a tracking record in the ``users_data`` table. The documentation refers to this as a ``user data`` or ``user data file`` record.
366//!
367//! - URL path: ``/user/data``
368//! - Method: ``POST``
369//! - Handler: [`upload_user_data`](crate::requests::user::upload_user_data::upload_user_data)
370//! - Request: [`ApiReqUserUploadData`](crate::requests::user::upload_user_data::ApiReqUserUploadData)
371//! - Response: [`ApiResUserUploadData`](crate::requests::user::upload_user_data::ApiResUserUploadData)
372//!
373//! #### Update an existing user data file record for a file stored in AWS S3
374//!
375//! Update the ``users_data`` tracking record for a file that exists in AWS S3
376//!
377//! - URL path: ``/user/data``
378//! - Method: ``PUT``
379//! - Handler: [`update_user_data`](crate::requests::user::update_user_data::update_user_data)
380//! - Request: [`ApiReqUserUpdateData`](crate::requests::user::update_user_data::ApiReqUserUpdateData)
381//! - Response: [`ApiResUserUpdateData`](crate::requests::user::update_user_data::ApiResUserUpdateData)
382//!
383//! #### Search for existing user data files from the db
384//!
385//! Search for matching records in the ``users_data`` db based off the request's values
386//!
387//! - URL path: ``/user/data/search``
388//! - Method: ``POST``
389//! - Handler: [`search_user_data`](crate::requests::user::search_user_data::search_user_data)
390//! - Request: [`ApiReqUserSearchData`](crate::requests::user::search_user_data::ApiReqUserSearchData)
391//! - Response: [`ApiResUserSearchData`](crate::requests::user::search_user_data::ApiResUserSearchData)
392//!
393//! ### User Authentication APIs
394//!
395//! #### User Login
396//!
397//! Log the user in and get a json web token (jwt) back for authentication on subsequent client requests
398//!
399//! - URL path: ``/login``
400//! - Method: ``POST``
401//! - Handler: [`login_user`](crate::requests::auth::login_user::login_user)
402//! - Request: [`ApiReqUserLogin`](crate::requests::auth::login_user::ApiReqUserLogin)
403//! - Response: [`ApiResUserLogin`](crate::requests::auth::login_user::ApiResUserLogin)
404//!
405//! # Interation Test Guide
406//!
407//! This project focused on integration tests for v1 instead of only rust tests (specifically everything has been tested with **curl**):
408//!
409//! Please refer to the latest [Integration Tests Using curl Guide](https://github.com/jay-johnson/restapi/blob/tests/integration-using-curl.md)
410//!
411//! ## Build and run the example server
412//!
413//! ```bash
414//! cargo build --example server && export RUST_BACKTRACE=1 && export RUST_LOG=info && ./target/debug/examples/server
415//! ```
416//!
417//! # Integration Tests Using curl Guide
418//!
419//! ## Set up bash curl tests
420//!
421//! ```bash
422//! export API_TLS_DIR="./certs/tls/api"
423//! export TLS_ARGS="--cacert ${API_TLS_DIR}/api-ca.pem \
424//!     --cert ${API_TLS_DIR}/api.crt \
425//!     --key ${API_TLS_DIR}/api.key"
426//! ```
427//!
428//! ## User APIs
429//!
430//! ### Login (user does not exist yet)
431//!
432//! ```bash
433//! curl -s ${TLS_ARGS} \
434//!     "https://0.0.0.0:3000/login" \
435//!     -XPOST \
436//!     -d '{"email":"user@email.com","password":"12345"}' | jq
437//! ```
438//!
439//! ### Create user
440//!
441//! ```bash
442//! curl -s ${TLS_ARGS} \
443//!     "https://0.0.0.0:3000/user" \
444//!     -XPOST \
445//!     -d '{"email":"user@email.com","password":"12345"}' | jq
446//! ```
447//!
448//! ### Login and save the token as an env variable
449//!
450//! ```bash
451//! export TOKEN=$(curl -s ${TLS_ARGS} \
452//!     "https://0.0.0.0:3000/login" \
453//!     -XPOST \
454//!     -d '{"email":"user@email.com","password":"12345"}' | jq -r '.token')
455//! ```
456//!
457//! ### Get user
458//!
459//! ```bash
460//! curl -s ${TLS_ARGS} \
461//!     "https://0.0.0.0:3000/user/1" \
462//!     -XGET \
463//!     -H "Bearer: ${TOKEN}" | jq
464//! ```
465//!
466//! ### Update user
467//!
468//! ```bash
469//! curl -s ${TLS_ARGS} \
470//!     "https://0.0.0.0:3000/user" \
471//!     -H "Bearer: ${TOKEN}" \
472//!     -XPUT \
473//!     -d '{"user_id":1,"email":"somenewemail@gmail.com","password":"321123","state":0}'
474//! ```
475//!
476//! ### Change user password
477//!
478//! #### Change to a new password
479//!
480//! ```bash
481//! curl -s ${TLS_ARGS} \
482//!     "https://0.0.0.0:3000/user" \
483//!     -H "Bearer: ${TOKEN}" \
484//!     -XPUT \
485//!     -d '{"user_id":1,"password":"12345a"}' | jq
486//! ```
487//!
488//! #### Change password back to the original
489//!
490//! ```bash
491//! curl -s ${TLS_ARGS} \
492//!     "https://0.0.0.0:3000/user" \
493//!     -H "Bearer: ${TOKEN}" \
494//!     -XPUT \
495//!     -d '{"user_id":1,"password":"12345"}' | jq
496//! ```
497//!
498//! ### Create a one-time-use-password (otp) allowing a user to reset their users.password from the users.email
499//!
500//! ```bash
501//! curl -s ${TLS_ARGS} \
502//!     "https://0.0.0.0:3000/user/password/reset" \
503//!     -H "Bearer: ${TOKEN}" \
504//!     -XPOST \
505//!     -d '{"user_id":1,"email":"user@email.com"}' | jq
506//! ```
507//!
508//! ### Consume user one-time-use-password token to reset the users.password (otp)
509//!
510//! ```bash
511//! curl -s ${TLS_ARGS} \
512//!     "https://0.0.0.0:3000/user/password/change" \
513//!     -H "Bearer: ${TOKEN}" \
514//!     -XPOST \
515//!     -d '{"user_id":1,"email":"user@email.com"}' | jq
516//! ```
517//!
518//! ### Change user email
519//!
520//! ```bash
521//! curl -s ${TLS_ARGS} \
522//!     "https://0.0.0.0:3000/user" \
523//!     -H "Bearer: ${TOKEN}" \
524//!     -XPUT \
525//!     -d '{"user_id":1,"email":"unique@gmail.com"}' | jq
526//! ```
527//!
528//! ### Verify user email
529//!
530//! ```bash
531//! curl -s ${TLS_ARGS} \
532//!     "https://0.0.0.0:3000/user/verify?u=1&t=2" | jq
533//! ```
534//!
535//! ### Search user (token must be for the POST-ed user id)
536//!
537//! ```bash
538//! curl -s ${TLS_ARGS} \
539//!     "https://0.0.0.0:3000/user/search" \
540//!     -XPOST \
541//!     -H "Bearer: ${TOKEN}" \
542//!     -d '{"email":"user","user_id":1}' | jq
543//! ```
544//!
545//! ### Delete user
546//!
547//! ```bash
548//! curl -s ${TLS_ARGS} \
549//!     "https://0.0.0.0:3000/user" \
550//!     -XDELETE \
551//!     -d '{"email":"user@email.com","user_id":1}' \
552//!     -H "Content-type: application/json" \
553//!     -H "Bearer: ${TOKEN}" | jq
554//! ```
555//!
556//! ## JWT (json web tokens)
557//!
558//! ### Configurable JWT Environment Variables
559//!
560//! #### Header key for the token:
561//!
562//! ```bash
563//! export TOKEN_HEADER="Bearer"
564//! ```
565//!
566//! #### Token Org (embedded in the jwt)
567//!
568//! ```bash
569//! export TOKEN_ORG="Org Name";
570//! ```
571//!
572//! #### Token Lifetime Duration
573//!
574//! ```bash
575//! # 30 days
576//! export TOKEN_EXPIRATION_SECONDS_INTO_FUTURE=2592000;
577//! # 7 days
578//! export TOKEN_EXPIRATION_SECONDS_INTO_FUTURE=604800;
579//! # 1 day
580//! export TOKEN_EXPIRATION_SECONDS_INTO_FUTURE=86400;
581//! ```
582//!
583//! #### JWT Signing Keys
584//!
585//! ```bash
586//! export TOKEN_ALGO_KEY_DIR="./jwt"
587//! export TOKEN_ALGO_PRIVATE_KEY_ORG="${TOKEN_ALGO_KEY_DIR}/private-key.pem"
588//! export TOKEN_ALGO_PRIVATE_KEY="${TOKEN_ALGO_KEY_DIR}/private-key-pkcs8.pem"
589//! export TOKEN_ALGO_PUBLIC_KEY="${TOKEN_ALGO_KEY_DIR}/public-key.pem"
590//! ```
591//!
592//! ##### Generate your own jwt keys with these commands
593//!
594//! These commands were tested on ubuntu 21.10 using bash:
595//!
596//! ```bash
597//! openssl ecparam -name prime256v1 -genkey -out "${TOKEN_ALGO_PRIVATE_KEY_ORG}"
598//! openssl pkcs8 -topk8 -nocrypt -in private-key.pem -out "${TOKEN_ALGO_PRIVATE_KEY}"
599//! openssl ec -in "${TOKEN_ALGO_PRIVATE_KEY_ORG}" -pubout -out "${TOKEN_ALGO_PUBLIC_KEY}"
600//! ```
601//!
602//! ## S3
603//!
604//! ### Setting up AWS credentials
605//!
606//! <https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html>
607//!
608//! ```bash
609//! export AWS_ACCESS_KEY_ID=ACCESS_KEY
610//! export AWS_SECRET_ACCESS_KEY=SECRET_KEY
611//! ```
612//!
613//! ### S3 Upload a user data file (no file type restrictions + s3 archival)
614//!
615//! ```bash
616//! export UPLOAD_FILE="./README.md"
617//! export DATA_TYPE="file"
618//! export S3_DATA_BUCKET="BUCKET_NAME"
619//! export S3_DATA_PREFIX="user/data/file"
620//! ```
621//!
622//! ```bash
623//! curl -s ${TLS_ARGS} \
624//!     -XPOST \
625//!     --data-binary "@${UPLOAD_FILE}" \
626//!     "https://0.0.0.0:3000/user/data" \
627//!     -H "Bearer: ${TOKEN}" \
628//!     -H 'user_id: 1' \
629//!     -H 'comments: this is a test comment' \
630//!     -H 'encoding: na' \
631//!     -H 'Content-type: text/txt' \
632//!     -H 'filename: README.md' \
633//!     -H "data_type: ${DATA_TYPE}" | jq
634//! ```
635//!
636//! ### Search user data (token must be for the POST-ed user id)
637//!
638//! ```bash
639//! curl -s ${TLS_ARGS} \
640//!     "https://0.0.0.0:3000/user/data/search" \
641//!     -XPOST \
642//!     -H "Bearer: ${TOKEN}" \
643//!     -d '{"user_id":1}' | jq
644//! ```
645//!
646//! ### Update a single user data record (token must be for the PUT user id)
647//!
648//! ```bash
649//! curl -s ${TLS_ARGS} \
650//!     "https://0.0.0.0:3000/user/data" \
651//!     -XPUT \
652//!     -H "Bearer: ${TOKEN}" \
653//!     -d '{"user_id":1,"data_id":1,"comments":"updated comment using curl"}' | jq
654//! ```
655//!
656//! ### Login and save the token as an env variable
657//!
658//! ```bash
659//! export TOKEN=$(curl -s ${TLS_ARGS} \
660//!     "https://0.0.0.0:3000/login" \
661//!     -XPOST \
662//!     -d '{"email":"user@email.com","password":"12345"}' | jq -r '.token')
663//! ```
664//!
665//! ## Postgres DB
666//!
667//! ### View DB Tables
668//!
669//! #### Connect to postgres using tls
670//!
671//! ```bash
672//! psql --set=sslmode=require -h 0.0.0.0 -p 5432 -U postgres -d mydb
673//! ```
674//!
675//! #### Get public tables in the mydb
676//!
677//! ```bash
678//! SELECT table_name FROM information_schema.tables WHERE table_schema='public';
679//! ```
680//!
681//! ## Podman Image Push
682//!
683//! ```bash
684//! cur_tag=$(cat Cargo.toml | grep version | head -1 | sed -e 's/"//g' | awk '{print $NF}')
685//! podman push IMAGE_ID "docker://docker.io/jayjohnson/rust-restapi:${cur_tag}"
686//! podman push IMAGE_ID "docker://docker.io/jayjohnson/rust-restapi:latest"
687//! podman push "docker.io/jayjohnson/rust-restapi:${cur_tag}"
688//! podman push "docker.io/jayjohnson/rust-restapi:latest"
689//! ```
690//!
691//! ## Helm Chart
692//!
693//! Please refer to the [Deploying the Rust Rest API helm chart into kubernetes guide](https://github.com/jay-johnson/restapi/blob/main/charts) for deploying the example helm chart into a kubernetes cluster.
694//!
695//! ## Build Docs
696//!
697//! ```bash
698//! cargo doc --example server
699//! ```
700
701extern crate pretty_env_logger;
702#[macro_use]
703extern crate log;
704extern crate chrono;
705extern crate serde;
706extern crate serde_json;
707extern crate uuid;
708
709// include files and sub directories
710pub mod core;
711pub mod handle_request;
712pub mod is3;
713pub mod jwt;
714pub mod kafka;
715pub mod monitoring;
716pub mod pools;
717pub mod requests;
718pub mod tls;
719pub mod utils;