Giter Site home page Giter Site logo

calvinlfer / weather-manager Goto Github PK

View Code? Open in Web Editor NEW
2.0 2.0 0.0 42 KB

A simple Weather Manager application using Akka HTTP and DynamoDB that interacts with OpenWeather

Scala 99.14% Groovy 0.86%
scala dynamodb jwt-tokens password-reset openweather akka-http akka akka-persistence cluster-sharding

weather-manager's Introduction

Weather manager

A simple REST API that is meant to manage a set of weather related data for a user.

Architecture

Authentication

This application makes use of JWT tokens to perform authentication. JWT tokens must be included in the Authorization header field (with value Bearer <token>) when trying to access protected endpoints. The HS256 algorithm for decoding and verifying JWT tokens which relies on secret text being shared.

Reset code via email is made possible by Courier. We rely on an existing SMTP compatible mail server (like GMail) to send out emails to users.

Application

The application uses Akka HTTP to serve HTTP requests and DynamoDB as the backing store. It also interacts with OpenWeather in order to source weather information. ScalaCache + Caffeine is also used to cache OpenWeather queries for 30 minutes to minimize latency and bandwidth.

It uses 3 DynamoDB tables:

  • Member: responsible for member authentication (passwords are bcrypted and then stored)
  • Forecast: OpenWeather forecast weather ID data is stored for each user
  • Password Reset: Table that is used to facilitate password reset functionality

Table Creation

If you are using local DynamoDB, hop on to the shell (eg. if Local DynamoDB runs on port 8000, visit http://localhost:8000/shell) and execute the following commands to configure the tables:

Table to store forecast data

var params = {
    TableName: 'forecast',
    KeySchema: [ // The type of of schema.  Must start with a HASH type, with an optional second RANGE.
        { // Required HASH type attribute
            AttributeName: 'username',
            KeyType: 'HASH',
        },
        { // Optional RANGE key type for HASH + RANGE tables
            AttributeName: 'id', 
            KeyType: 'RANGE', 
        }
    ],
    AttributeDefinitions: [ // The names and types of all primary and index key attributes only
        {
            AttributeName: 'username',
            AttributeType: 'S', // (S | N | B) for string, number, binary
        },
        {
            AttributeName: 'id',
            AttributeType: 'N', // (S | N | B) for string, number, binary
        }
    ],
    ProvisionedThroughput: { // required provisioned throughput for the table
        ReadCapacityUnits: 1, 
        WriteCapacityUnits: 1, 
    }
};
dynamodb.createTable(params, function(err, data) {
    if (err) ppJson(err); // an error occurred
    else ppJson(data); // successful response
});

Table to store member data

var params = {
    TableName: 'forecast-members',
    KeySchema: [ // The type of of schema.  Must start with a HASH type, with an optional second RANGE.
        { // Required HASH type attribute
            AttributeName: 'email',
            KeyType: 'HASH',
        }
    ],
    AttributeDefinitions: [ // The names and types of all primary and index key attributes only
        {
            AttributeName: 'email',
            AttributeType: 'S', // (S | N | B) for string, number, binary
        }
    ],
    ProvisionedThroughput: { // required provisioned throughput for the table
        ReadCapacityUnits: 1, 
        WriteCapacityUnits: 1, 
    }
};
dynamodb.createTable(params, function(err, data) {
    if (err) ppJson(err); // an error occurred
    else ppJson(data); // successful response
});

Table to store password reset data

var params = {
    TableName: 'forecast-password-reset',
    KeySchema: [ // The type of of schema.  Must start with a HASH type, with an optional second RANGE.
        { // Required HASH type attribute
            AttributeName: 'resetCode',
            KeyType: 'HASH',
        }
    ],
    AttributeDefinitions: [ // The names and types of all primary and index key attributes only
        {
            AttributeName: 'resetCode',
            AttributeType: 'S', // (S | N | B) for string, number, binary
        }
    ],
    ProvisionedThroughput: { // required provisioned throughput for the table
        ReadCapacityUnits: 1, 
        WriteCapacityUnits: 1, 
    }
};
dynamodb.createTable(params, function(err, data) {
    if (err) ppJson(err); // an error occurred
    else ppJson(data); // successful response
});

Running the application

The easiest way to run the application is using IntellIJ, if you want to run this against local DynamoDB then add the following to the VM properties in the Run Configuration:

-Dsecrets.jwt-key=examplesecretgoes here -Ddynamodb.aws-access-key-id=dev -Ddynamodb.aws-secret-access-key=dev -Ddynamodb.endpoint=http://localhost:8000 [email protected] -Demail.password=yourpassword -Dopenweather.api-key=youropenweatherapikey

You can also use the universal packager which is more geared for production deployment

sbt clean universal:packageBin 

Navigate to target/universal and unzip weather-manager-1.0.zip and execute ./bin/weather-manager and ensure the following environment variables are present:

  • FORECAST_TABLE: name of table to manage forecast data for users
  • MEMBER_TABLE: name of table to manage user authentication
  • PASSWORD_RESET_TABLE: name of table to handle password resets for users
  • SMTP_SERVER: domain of SMTP server (e.g. smtp.gmail.com)
  • SMTP_PORT: port of SMTP server
  • SENDER_EMAIL: email that is used to send password resets
  • SENDER_PASSWORD: password belonging to the email
  • JWT_SECRET: the secret used to encrypt JWT messages
  • JWT_EXPIRY: the time (in seconds) that the JWT token is valid for

If you want to run this against local DynamoDB then ensure you have these system properties as well:

-Ddynamodb.aws-access-key-id=dev -Ddynamodb.aws-secret-access-key=dev -Ddynamodb.endpoint=http://localhost:8000

You can also use the system properties mentioned above as an alternative to environment variables. For example:

./bin/weather-manager -Dsecrets.jwt-key=examplesecretgoes here -Ddynamodb.aws-access-key-id=dev -Ddynamodb.aws-secret-access-key=dev -Ddynamodb.endpoint=http://localhost:8000 [email protected] -Demail.password=yourpassword -Dopenweather.api-key=youropenweatherapikey

weather-manager's People

Contributors

calvinlfer avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.