BeeCompanion is a platform for both beekeepers and their supporters.
This project is based on Angular2 Webpack Starter from AngularClass.
It supports:
We use the component approach in our project. This is the new standard for developing Angular apps and a great way to ensure maintainable code by encapsulation of our behavior logic. A component is basically a self contained app usually in a single file or a folder with each concern as a file: style, template, specs, e2e, and component class. Here's how it looks (overview):
bee-companion/
├──api/ * our API
│ ├──config * our API configuration
│ ├──migrations * sequelize migrations
│ ├──models * our API models
│ ├──routes * our API routes
│ ├──routes-external * our API routes to external services
│ ├──seeders * database seeds
│ └──api.js * entry point of our API
│
├──config/ * our configuration
│ ├──dbconfig.js * our database configuration
│ ├──font-awesome.config.js * font-awesome configuration
│ ├──head-config.common.js * header tags injected into html
│ ├──helpers.js * helper functions for our configuration files
│ ├──karma.conf.js * karma config for our unit tests
│ ├──protractor.conf.js * protractor config for our end-to-end tests
│ ├──spec-bundle.js * ignore this magic that sets up our Angular testing environment
│ ├──webpack.dev.js * our development webpack config
│ ├──webpack.prod.js * our production webpack config
│ └──webpack.test.js * our testing webpack config
│
├──deployment/ * deployment scripts and configurations
│ ├──application-start.sh * a shell script to install and run our application on prod server
│ └──jenkins.sh * a shell script to install, run and test our application on Jenkins
│
├──src/ * our source files that will be compiled to javascript
│ ├──main.browser.ts * our entry file for our browser environment
│ │
│ ├──index.html * Index.html: where we generate our index page
│ │
│ ├──polyfills.ts * our polyfills file
│ │
│ ├──app/ * WebApp: folder
│ │ ├──app.component.spec.ts * a simple test of components in app.component.ts
│ │ ├──app.e2e.ts * a simple end-to-end test for /
│ │ └──app.component.ts * a simple version of our App component components
│ │
│ └──assets/ * static assets are served here
│ ├──icon/ * our list of icons from www.favicon-generator.org
│ ├──service-worker.js * ignore this. Web App service worker that's not complete yet
│ ├──robots.txt * for search engines to crawl your website
│ └──humans.txt * for humans to know who the developers are
│
│
├──.bootstraprc * Bootstrap config
├──.sequelizerc * Sequelize ORM config
├──appspec.yml * Amazon Web Services configuration for CD/CI
├──package.json * what npm uses to manage it's dependencies
├──tsconfig.json * typescript config used outside webpack
├──tsconfig.webpack.json * config that webpack uses for typescript
├──tslint.json * typescript lint config
├──typedoc.json * typescript documentation generator
└──webpack.config.js * webpack main configuration file
What you need to run this app:
node
andnpm
- Ensure you're running the latest versions Node
v6.x.x
+ (orv7.x.x
) and NPM3.x.x
+
If you have
nvm
installed, which is highly recommended (brew install nvm
) you can do anvm install --lts && nvm use
in$
to run with the latest Node LTS. You can also have thiszsh
done for you automatically
Once you have those, you should install these globals with npm install --global
:
webpack
(npm install --global webpack
)webpack-dev-server
(npm install --global webpack-dev-server
)karma
(npm install --global karma-cli
)protractor
(npm install --global protractor
)typescript
(npm install --global typescript
)sequelize-cli
(npm install --global sequelize-cli
)npm-check
(npm install --global npm-check
)nsp
(npm install --global nsp
)
A local postgres database: Postgres
For testing:
As we use headless chrome for testing purpose you need Chrome 59 Beta
npm install
to install all local dependencies
BeeCompanion uses Sequelize ORM for database requests via API. The database configuration is placed at config/dbconfig.js
.
For development we recommend to create a postgresql database named beecompanion-development
.
# development
sequelize db:migrate --env development
# test
sequelize db:migrate --env test
# production
sequelize db:migrate --env production
After you have installed all dependencies you can now run the app. Run npm run server:dev
to start a local server using webpack-dev-server
which will watch, build (in-memory), and reload for you. The port will be displayed to you as http://0.0.0.0:8000
. Additionally, run npm run api:dev
to start the API. The port will be displayed to you as http://0.0.0.0:3000
.
# development
npm run server:dev
# production
npm run build:prod
npm run server:prod
# production using pm2 (living forever)
npm run build:prod
npm run server:prod:pm2
# development
npm run api:dev
# production
npm run api:prod
# production using pm2 (living forever)
npm run api:prod:pm2
# development
npm run build:dev
# production (jit)
npm run build:prod
# AoT
npm run build:aot
npm run server:dev:hmr
npm run watch
npm run test
npm run watch:test
# update Webdriver (optional, done automatically by postinstall script)
npm run webdriver:update
# this will start a test server and launch Protractor
npm run e2e
# this will test both your JIT and AoT builds
npm run ci:testall
npm run e2e:live
BeeCompanion uses AWS Codepipeline and Jenkins for CD/CI.
The pipeline perodically polls this repository for changes, if something has changed the project is send to Jenkins where the project is built, run and tested. If all tests have been passed, the project is deployed to the production server.
The configuration for this process is spread over the following files:
appspec.yml
contains the deployment configurationdeployment/application-start.sh
contains the install and build commands for the deploymentdeployment/jenkins.sh contains
the install, build and test commands for Jenkins
Environment variables for both test and production are loaded by Dotenv.
For that reason, a .env
file which declares those variables is placed in the root directory of the project
(deployment and Jenkins).
It is important that not only those files but also the sample.env (root of this repository) are kept up-to-date.
The update of those files must be done before releasing any changes, otherwise the deployment will fail.
- Be aware of OWASP Top 10
- Keep servers up-to-date
- Keep packages up-to-date and secure
- Be careful with sensitive data (company data and user data)
- Keep in mind that security is more important than any new feature
Angular already handles most security problems by default, for example, Angular treats all values as untrusted by default. However, it is important to follow Angular's best practices and to keep frontend security in mind in all stages of development. Please inform yourself regularly about the latest security recommendations of Angular which can be found in Angular's Guide Security Section.
Be aware that you must not include any sensitive information (e. g. credentials, API keys, etc.) directly in typescript.
Instead, include them via config/webpack.dev.js
/ config/webpack.prod.js
/ config/webpack.test.js
.
How does that work:
- Add the value to
.env
in the project's root (do not forget to update sample.env too) - Create a new constant and read the value from process environment under Webpack Constants section
in
config/webpack.env.js
, for example,const MY_SECRET_VARIABLE = process.env.MY_SECRET_VARIABLE;
- Add an entry to const METADATA which can be found directly under Webpack Constants section,
for example,
MY_SECRET_VARIABLE: MY_SECRET_VARIABLE
- Go to plugins section and search for
new DefinePlugin
, and add a new entry toprocess.env
, for example,MY_SECRET_VARIABLE': JSON.stringify(MY_SECRET_VARIABLE)
- Go to
src/app/custom-typings.d.ts
and add a new entrydeclare var MY_SECRET_VARIABLE: string;
- Add a new entry to interface GlobalEnvironment
MY_SECRET_VARIABLE: string;
All variables defined in .env
are then loaded as environment variables
by Dotenv and are accessible in
TypeScript via process.env.MY_SECRET_VARIABLE
.
There are several security aspects which have to be kept in mind during development, plus several security concepts which have already been implemented:
- The Helmet packages has been integrated into our API. It comes along with several security concepts (HTTP Security Headers), some are enabled by default, while some have to be activated and configured manually. It is important to always trade of the benefits against the drawbacks of each component. We decided to additionally activate HTTP Public Key Pinning, referrerPolicy and contentSecurityPolicy to prevent man-in-the-middle attacks, to increase privacy, and to prevent XSS attacks.
- Avoid to use
bodyParser.urlencoded
if not necessary, meaning API does not get any content other than JSON.bodyParser.urlencoded
enables CSRF attacks if no CSRF token is used on each request. For more info see Dangerous Use of Express Body-Parser - The Cors package has been integrated into our API.
It enables us to do Cross Origin Request Sharing. It is important to keep some points in mind:
- Do not enable cors for each route, instead enable it only for those
routes which have need of cors. This can be done with
router.use('/route', cors(corsConfig));
- Only allow specific origins by declaring them using the whitelist in
api/config/cors.js
- Only allow methods, allow headers and credentials if needed in
api/config/cors.js
- Do not enable cors for each route, instead enable it only for those
routes which have need of cors. This can be done with
- If sessions are needed use either Express-Session
or Cookie-Session depending on the use case. Both
packages are developed and maintained by ExpressJS
so do not use other packages for session handling. Additionally, it is important to correctly configure the session:
- Do not use the default session name
- Set HttpOnly property to true to ensure the cookie cannot be read by JavaScript
- Set Secure property to true to ensure that the cookie is only send via HTTPS
- Set the expire property to a date in the near future (a cookie should only live as long as necessary)
- Set domain and sameSite properties if possible
For further security best practices according to ExpressJS have a look at the following resources:
For frontend performance we recommend to follow Angular Deployment Guide. Especially, the AoT section may be of highest interest.
For AoT there are additional recommendations:
- Don’t use require statements for your templates or styles, use styleUrls and templateUrls, the angular2-template-loader plugin will change it to require at build time.
- Don’t use default exports.
- Don’t use
form.controls.controlName
, useform.get(‘controlName’)
- Don’t use
control.errors?.someError
, usecontrol.hasError(‘someError’)
- Don’t use functions in your providers, routes or declarations, export a function and then reference that function name.
- @Inputs, @Outputs, View or Content Child(ren), Hostbindings, and any field you use from the template or annotate for Angular should be public.
For backend performance we recommend to follow ExpressJS - Production best practices: performance and reliability.
The project is currently under development and underlies the copyright law.