sequenceDiagram
participant B as Browser
participant E as Ember App
participant D as Apollo
participant A as API
B->>E: GET request
E->>D: request data
D->>A: ajax request
A->>D: resolved request
D->>E: return data
E->>B: render template with data
sequenceDiagram
participant C as Client/CMS
participant A as API
participant R as Route Manager
participant V as View
participant J as JWT Authenticator
participant S as Schema
participant M as Model
participant O as ORM(SQLAlchemy)
C->>A: REST request
A->>R: Map route to View
R->>V: Load View for Route
V-->J: Validate authentication, if required
J-->S: Load View Schema
V->>S: Load View Schema
S->>M: Load Model to generate query
M->>O: Request transaction from generated query
O->>M: Return SQL result
M->>S: Parse results into the Model class
S->>V: Return collection of objects or single object
V->>R: Return response object
R->>A: Resolve request object
A->>C: Serve data
REST diagram
sequenceDiagram
participant C as Client/CMS
participant A as API
participant R as Route Manager
participant V as View
participant J as JWT Authenticator
participant S as Graphql Schema
participant Q as Graphql Query
participant M as Model
participant O as ORM(SQLAlchemy)
C->>A: REST request
A->>R: Map route to View
R->>V: Load View for Route
V->>J: Validate authentication, if required
J->>S: Load Graphql Schema
S->>Q: Process Graphql query or mutation
Q->>M: Load Model to generate query
M->>O: Request transaction from generated query
O->>M: Return SQL result
M->>Q: Parse results into the Model class
Q->>S: Return results with pagination
S->>V: Return collection of objects or single object
V->>R: Return response object
R->>A: Resolve request object
A->>C: Serve data
Graphql diagram
sequenceDiagram
participant F as Flask Framework
participant M as SQL Alchemy Model
participant O as ORM(SQLAlchemy)
F->>M: REST request
M->>O: Send SQL statement
O->>M: Return results
Note left of M: Processing of computed and hybrid properties, and attribute observers
M->>F: Convert rows to model objects
sequenceDiagram
participant O as ORM(SQLAlchemy)
participant D as DB(Database)
O-->>D: Send SQL statement
Note left of D: SQL Statement is added to the transactions queue
D-->>O: Convert rows to model objects
sequenceDiagram
participant R as RDS Instance
participant P as PGSQL DB Engine
R-->>P: process transaction
Note left of P: SQL transactions queue
P-->>R: processed transaction
The API makes use of the logs setup provided by AWS EB, the EB service provides Cloudwatch logs, which outputs the events from the Python application.
- /var/logs/httpd/error_log
- /var/logs/httpds/access_log
- /var/logs/eb-activity.log
Important logs provied by AWS EB
In order to access the logs mentioned above you will need to access to the AWS account that is hosting the API. The logs are available in the EB console, you can either download a .zip
file with the full logs or just pull the last 100 lines of each log file.
The CMS makes use of ember-notifications
addon to display the errors coming from failed requests to the API.
The API has custom exceptions and makes use of exceptions provided by Graphene
and Flask
.
The custom exceptions can be found under the following path app/exceptions
- AttachmentTooLarge
- LoginRequired
- ParseError
- PermissionDenied
- UnsupportedMediaType
- InvalidParameters
Custom exceptions
Each custom exception inherits from JsonApiException
which is provided by the flaks-rest-jsonapi
framework, you can find more information about the JsonApiException
class here.
The CMS makes use of native javascript error class only in cases where the application can't continue if a certain condition is not met. Here is an example of the use case:
somemethod() {
const IMPORTANT_ENV = {process.env};
if (!IMPORTANT_ENV) {
throw new Error('IMPORTANT_ENV is required');
}
}
The API secures non public endpoints by using the JWTRequired
view mixin, this mixin is extended from the three secured base view classes which are located in the app/views/base.py
file.
- SecureResourceList
- SecureResourceDetail
- SecureResourceRelationship
Base secured view classes
All of these views are an extension from the Flask REST JSON Api
framework resource view classes:
- ResourceList
- ResourceDetail
- ResourceRelationship
For more infomation about resource view classes click here
Bellow you will find information about the Okta implementation, which covers the authentication process from the ember application standpoint
It validates that there's a valid JWT token in the request payload, besides validating that there's a valid JWT token it matches that the identity in the token is a valid user id in the users tables from the Aurora database.
Besides validating that the identity matches an existing user, it also identifies if the JWT token comes from the Aurora CMS or the PA Client, the reason it needs to distinguis between both user types is because this drives enforced filters in models and the source of the products data.
Bearer eyJraWQiOiJNSEJJMVJFQkVka3Q2bHRfVWk5QS05U3ZURkVVY2ZWT2FFODFVMzVrN28wIiwiYWxnIjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULmxSUk1DWUVxbEdNMVZYMHpPX1hIS3VvY0p5VEV2YnNUSWMyaVktU2R3YjAiLCJpc3MiOiJodHRwczovL3BzLXNpZW1lbnMub2t0YXByZXZpZXcuY29tL29hdXRoMi9hdXNjcTZ4aTF2b0hneUdBSTBoNyIsImF1ZCI6Imh0dHBzOi8vYXVyb3JhLWRldi5taW5kc3BoZXJlLnNpZW1lbnMuY29tIiwiaWF0IjoxNTE4MDY3MjQ0LCJleHAiOjE1MTgwNzQ0NDQsImNpZCI6IjBvYWNjbHB6cnQ5aTVRTXBjMGg3IiwidWlkIjoiMDB1Y3Frbmlnd0tJR2xXekQwaDciLCJzY3AiOlsib3BlbmlkIiwicGhvbmUiLCJhZGRyZXNzIiwiZW1haWwiLCJwcm9maWxlIiwiY21zIl0sInN1YiI6InJvZHJpZ29AZnVsbHN0YWNrbGFicy5jbyIsInBhIjp0cnVlLCJwb3J0YWxfYWRtaW4iOmZhbHNlLCJjbXMiOnRydWUsImVtcGxveWVlIjp0cnVlLCJjbXNfYWRtaW4iOnRydWUsImN1cnJlbnRfYXBwX2lzX2NtcyI6dHJ1ZX0.LK_kBgnTU6rrzUzMkCIFAnOVAaUra8F4jCV3F8IcNUSfQBAVd_5abT5rAbH56CJdb87cu78YJmyjcb6kuOteAXSkwHwmhTGSiBuVZQhHuQcOYdbW2CluZb6mfd9hCTrD8i5hdjbeq0dH5nVRD5DViBQbyTjEkJcxsk66apRW01bm_aYbc3ygNkOr_9CZcCcwmYM_3_zajjWKLG6gTc32j3nnmxpI4PY9tBb99TD6pMLz8TwZBFDp1tXMdZvGO1OyaEIw-jDi-BnrEYk5aYQOEbtOADSY8lX5MdpvEDUK1cqRHuxyUaY8LQPbr3vYkkSI51nATbEQiCa7gRGSuNX9dQ
Example of the JWT Token
{
"ver": 1,
"jti": "AT.lRRMCYEqlGM1VX0zO_XHKuocJyTEvbsTIc2iY-Sdwb0",
"iss": "https://ps-siemens.oktapreview.com/oauth2/auscq6xi1voHgyGAI0h7",
"aud": "https://aurora-dev.mindsphere.siemens.com",
"iat": 1518067244,
"exp": 1518074444,
"cid": "0oacclpzrt9i5QMpc0h7",
"uid": "00ucqknigwKIGlWzD0h7",
"scp": [
"openid",
"phone",
"address",
"email",
"profile",
"cms"
],
"sub": "rodrigo@fullstacklabs.co",
"pa": true,
"portal_admin": false,
"cms": true,
"employee": true,
"cms_admin": true,
"current_app_is_cms": true
}
Anatomy of the contents in a JWT Token
This mixin is used to restrict access to routes based on the logged in user type, there are certain routes that are required to be restricted for PA client users, this view mixin makes use of the data layer customizations from the Flask REST JSON Api
framework.
For more information about the Flask REST JSON Api data layers click here
As of right now there aren't any known security vulnerabilities
There isn't any caching implemented on the API
In the CMS we make use of the ember-apollo-client
addon, this addon allows ember applications to perform requests with graphql queries, the addon provides a data store that can cache graphql queries results.
Given the fact that we need to display the latest data in the CMS application, we are not using apollo cache.
For more information about the ember-apollo-client addon click here
The Aurora applications supports language based content for product, variant, and asset captions resources. Currently we only support two languages(German and English), more languages can be integrated into the applications by adding new language records to the languages table.
The production database is located in the Frankfurt region of AWS, all of the records keep track of created and updated dates, the dates use CET timezone.