Skip to content

Instantly share code, notes, and snippets.

@rodrigomf24
Last active February 8, 2018 15:06
Show Gist options
  • Save rodrigomf24/c876184dbf7b75504652fbce102e8f5f to your computer and use it in GitHub Desktop.
Save rodrigomf24/c876184dbf7b75504652fbce102e8f5f to your computer and use it in GitHub Desktop.
product-advisor-documentation

Solution Diagram

Presentation Layer

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
Loading

Service Layer

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
Loading

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
Loading

Graphql diagram

Business Layer

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  
Loading

Data Access Layer

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  
Loading

DB Layer

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
Loading

Framework

Logging

API - AWS EB(Elastic Beanstalk) Logs

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.

CMS

The CMS makes use of ember-notifications addon to display the errors coming from failed requests to the API.

Exception Handling

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.

CMS

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');
	}
}

Security

Authentication & Authorizations - API

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

JWTRequiredToken Mixin

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

ViewRestrictionByUserType Mixin

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

Other Security Vulnerabilities

As of right now there aren't any known security vulnerabilities

Caching

API

There isn't any caching implemented on the API

CMS

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

Internationalization & Localization

Internationalization API & CMS

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.

Localization

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.

Backend Jobs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment