-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial implementation #1
Changes from 16 commits
e74b8c8
629fc8a
4a11b02
edfd3b7
502aa2a
29c75c1
596675e
948098d
5cf4941
ead5325
f1a38fb
2de6d39
a84344a
e684083
2c61d6b
1dae070
a4a88a5
2dbe39d
fdef967
aa07594
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# This file contains the configuration for Credo and you are probably reading | ||
# this after creating it with `mix credo.gen.config`. | ||
# | ||
# If you find anything wrong or unclear in this file, please report an | ||
# issue on GitHub: https://github.com/rrrene/credo/issues | ||
# | ||
%{ | ||
# | ||
# You can have as many configs as you like in the `configs:` field. | ||
configs: [ | ||
%{ | ||
# | ||
# Run any config using `mix credo -C <name>`. If no config name is given | ||
# "default" is used. | ||
name: "default", | ||
# | ||
# These are the files included in the analysis: | ||
files: %{ | ||
# | ||
# You can give explicit globs or simply directories. | ||
# In the latter case `**/*.{ex,exs}` will be used. | ||
included: ["lib/", "src/", "web/", "apps/"], | ||
excluded: [~r"/_build/", ~r"/deps/"] | ||
}, | ||
# | ||
# If you create your own checks, you must specify the source files for | ||
# them here, so they can be loaded by Credo before running the analysis. | ||
requires: [], | ||
# | ||
# Credo automatically checks for updates, like e.g. Hex does. | ||
# You can disable this behaviour below: | ||
check_for_updates: true, | ||
# | ||
# If you want to enforce a style guide and need a more traditional linting | ||
# experience, you can change `strict` to `true` below: | ||
strict: true, | ||
# | ||
# If you want to use uncolored output by default, you can change `color` | ||
# to `false` below: | ||
color: true, | ||
# | ||
# You can customize the parameters of any check by adding a second element | ||
# to the tuple. | ||
# | ||
# To disable a check put `false` as second element: | ||
# | ||
# {Credo.Check.Design.DuplicatedCode, false} | ||
# | ||
checks: [ | ||
{Credo.Check.Consistency.ExceptionNames}, | ||
{Credo.Check.Consistency.LineEndings}, | ||
{Credo.Check.Consistency.MultiAliasImportRequireUse}, | ||
{Credo.Check.Consistency.ParameterPatternMatching}, | ||
{Credo.Check.Consistency.SpaceAroundOperators}, | ||
{Credo.Check.Consistency.SpaceInParentheses}, | ||
{Credo.Check.Consistency.TabsOrSpaces}, | ||
|
||
# For some checks, like AliasUsage, you can only customize the priority | ||
# Priority values are: `low, normal, high, higher` | ||
{Credo.Check.Design.AliasUsage, priority: :low}, | ||
|
||
# For others you can set parameters | ||
|
||
# If you don't want the `setup` and `test` macro calls in ExUnit tests | ||
# or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just | ||
# set the `excluded_macros` parameter to `[:schema, :setup, :test]`. | ||
{Credo.Check.Design.DuplicatedCode, excluded_macros: []}, | ||
|
||
# You can also customize the exit_status of each check. | ||
# If you don't want TODO comments to cause `mix credo` to fail, just | ||
# set this value to 0 (zero). | ||
{Credo.Check.Design.TagTODO, exit_status: 2}, | ||
{Credo.Check.Design.TagFIXME}, | ||
|
||
{Credo.Check.Readability.FunctionNames}, | ||
{Credo.Check.Readability.LargeNumbers}, | ||
{Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 80}, | ||
{Credo.Check.Readability.ModuleAttributeNames}, | ||
{Credo.Check.Readability.ModuleDoc}, | ||
{Credo.Check.Readability.ModuleNames}, | ||
{Credo.Check.Readability.NoParenthesesWhenZeroArity}, | ||
{Credo.Check.Readability.ParenthesesInCondition}, | ||
{Credo.Check.Readability.PredicateFunctionNames}, | ||
{Credo.Check.Readability.PreferImplicitTry}, | ||
{Credo.Check.Readability.RedundantBlankLines}, | ||
{Credo.Check.Readability.Specs}, | ||
{Credo.Check.Readability.StringSigils}, | ||
{Credo.Check.Readability.TrailingBlankLine}, | ||
{Credo.Check.Readability.TrailingWhiteSpace}, | ||
{Credo.Check.Readability.VariableNames}, | ||
{Credo.Check.Refactor.DoubleBooleanNegation}, | ||
|
||
# {Credo.Check.Refactor.CaseTrivialMatches}, # deprecated in 0.4.0 | ||
{Credo.Check.Refactor.ABCSize}, | ||
{Credo.Check.Refactor.CondStatements}, | ||
{Credo.Check.Refactor.CyclomaticComplexity}, | ||
{Credo.Check.Refactor.FunctionArity}, | ||
{Credo.Check.Refactor.MatchInCondition}, | ||
{Credo.Check.Refactor.NegatedConditionsInUnless}, | ||
{Credo.Check.Refactor.NegatedConditionsWithElse}, | ||
{Credo.Check.Refactor.Nesting}, | ||
{Credo.Check.Refactor.PipeChainStart}, | ||
{Credo.Check.Refactor.UnlessWithElse}, | ||
{Credo.Check.Refactor.VariableRebinding}, | ||
|
||
{Credo.Check.Warning.BoolOperationOnSameValues}, | ||
{Credo.Check.Warning.IExPry}, | ||
{Credo.Check.Warning.IoInspect}, | ||
{Credo.Check.Warning.NameRedeclarationByAssignment}, | ||
{Credo.Check.Warning.NameRedeclarationByCase}, | ||
{Credo.Check.Warning.NameRedeclarationByDef}, | ||
{Credo.Check.Warning.NameRedeclarationByFn}, | ||
{Credo.Check.Warning.OperationOnSameValues}, | ||
{Credo.Check.Warning.OperationWithConstantResult}, | ||
{Credo.Check.Warning.UnusedEnumOperation}, | ||
{Credo.Check.Warning.UnusedFileOperation}, | ||
{Credo.Check.Warning.UnusedKeywordOperation}, | ||
{Credo.Check.Warning.UnusedListOperation}, | ||
{Credo.Check.Warning.UnusedPathOperation}, | ||
{Credo.Check.Warning.UnusedRegexOperation}, | ||
{Credo.Check.Warning.UnusedStringOperation}, | ||
{Credo.Check.Warning.UnusedTupleOperation}, | ||
|
||
# Custom checks can be created using `mix credo.gen.check`. | ||
# | ||
] | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
language: elixir | ||
elixir: | ||
- 1.4.1 | ||
otp_release: | ||
- 19.2 | ||
|
||
sudo: required | ||
services: | ||
- docker | ||
|
||
before_script: | ||
- tools/travis-setup.sh | ||
|
||
env: | ||
- PRESET=exunit MIX_ENV=test | ||
- PRESET=credo MIX_ENV=test | ||
- PRESET=dialyzer MIX=test | ||
|
||
script: tools/travis-test.sh |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,144 @@ | ||
# MongoosePush | ||
|
||
**TODO: Add description** | ||
[![Build Status](https://travis-ci.org/esl/MongoosePush.svg?branch=initial_implementation)](https://travis-ci.org/esl/MongoosePush) [![Coverage Status](https://coveralls.io/repos/github/esl/MongoosePush/badge.svg?branch=initial_implementation)](https://coveralls.io/github/esl/MongoosePush?branch=initial_implementation) | ||
|
||
## Installation | ||
**MongoosePush** is simple (seriously) **REST** service written in **Elixir** providing ability to **send push | ||
notification** to `FCM` (Firebase Cloud Messaging) and/or | ||
`APNS` (Apple Push Notification Service) via their `HTTP/2` API. | ||
|
||
If [available in Hex](https://hex.pm/docs/publish), the package can be installed | ||
by adding `mongoose_push` to your list of dependencies in `mix.exs`: | ||
## Quick start | ||
|
||
### Docker | ||
|
||
Soon :) | ||
|
||
### Local build | ||
|
||
#### Perquisites | ||
|
||
* Elixir (http://elixir-lang.org/install.html) | ||
* Rebar3 (just enter ```mix local.rebar```) | ||
|
||
#### Build and run | ||
|
||
Build step is really easy. Just type in root of the repository: | ||
```bash | ||
MIX_ENV=prod mix do certs.dev, deps.get, compile, release | ||
``` | ||
|
||
After this step you may try to run the service via: | ||
```bash | ||
_build/prod/rel/mongoose_push/bin/mongoose_push console | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want to be serious, we really need to support releases. I won't accept an OS PR that has on support for releases :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you elaborate? What do you mean by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Damn...how could I have missed that? Sorry, of course you do support releases with distillery. Awesome :) |
||
|
||
Yeah, I know... It crashed. Running this service is fast and simple but unfortunately you can't have push notifications without properly configured `FCM` and/or `APNS` service. So, lets configure it! | ||
|
||
## Configuration | ||
|
||
The whole configuration is contained in file `config/{prod|dev|test}.exs` depending on with `MIX_ENV` you will be using. You should use `MIX_ENV=prod` for production installations and `MIX_ENV=dev` for you development. Anyway, lets take a look on `config/prod.exs`, part by part. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. your* :) |
||
|
||
### REST API configuration | ||
|
||
```elixir | ||
config :maru, MongoosePush.Router, | ||
versioning: [ | ||
using: :path | ||
], | ||
https: [ | ||
ip: {127, 0, 0, 1}, | ||
port: 8443, | ||
keyfile: "priv/ssl/fake_key.pem", | ||
certfile: "priv/ssl/fake_cert.pem", | ||
otp_app: :mongoose_push | ||
] | ||
``` | ||
|
||
This part of configuration relates only to `REST` endpoints that `MongoosePush` exposes. Here you can set bind IP adress (option: `ip`), port and paths to you `HTTP` `TLS` certificates. You should ignore other options unless you know what you're doing or you're going to get to know by reading [maru's documentation](https://maru.readme.io/docs). | ||
|
||
You may entirely skip the `maru` config entry to disable `REST` API and just use this project as `Elixir` library. | ||
|
||
### FCM configuration | ||
Lets take a look at sample `FCM` service configuration: | ||
```elixir | ||
def deps do | ||
[{:mongoose_push, "~> 0.1.0"}] | ||
end | ||
config :mongoose_push, fcm: [ | ||
default: [ | ||
key: "fake_app_key", | ||
pool_size: 5, | ||
mode: :prod | ||
] | ||
] | ||
``` | ||
|
||
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) | ||
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can | ||
be found at [https://hexdocs.pm/mongoose_push](https://hexdocs.pm/mongoose_push). | ||
The first level keyword list is a pool definition. You may have several named pools of different sizes and with different configurations. Currently the only reason you may want to do this is that, the `REST` client may switch between them by specifying matching `:mode` in their push request. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "The first level keyword list is a pool definition." - this is not very understandable. Maybe start with "to setup a pool...". |
||
|
||
Each `FCM` pool may be configured by setting the following fields: | ||
* **key** (*required*) - you `FCM` Application Key for using Googles API | ||
* **pool_size** (*required*) - maximum number of used `HTTP/2` connections to google's service | ||
* **mode** (*either `:prod` or `:dev`*) - pool's mode. `REST` client may select pool used to push his notification by specifying matching option in his request | ||
* **endpoint** (*optional*) - URL override for `FCM` service. Useful mainly in tests | ||
|
||
You may entirely skip the `FCM` config entry to disable `FCM` support. | ||
|
||
### APNS configuration | ||
|
||
Lets take a look at sample `APNS` service configuration: | ||
```elixir | ||
config :mongoose_push, apns: [ | ||
dev: [ | ||
cert: "priv/apns/dev_cert.pem", | ||
key: "priv/apns/dev_key.pem", | ||
mode: :dev, | ||
use_2197: false, | ||
pool_size: 5 | ||
], | ||
prod: [ | ||
cert: "priv/apns/prod_cert.pem", | ||
key: "priv/apns/prod_key.pem", | ||
mode: :prod, | ||
use_2197: false, | ||
pool_size: 5 | ||
] | ||
] | ||
``` | ||
Analogically to `FCM` configuration, at top level we may specify named pools that have different configurations. For `APNS` this is specifically useful since Apple delivers different APS certificated for development and production use. As in `FCM`, `REST` client may select named pool by providing matching `:mode` in his `REST` request. | ||
|
||
Each `APNS` pool may be configured by setting the following fields: | ||
* **cert** (*required*) - relative path to `APNS` `PEM` certificate issued by Apple. This certificate have to be somewhere in `priv` directory | ||
* **key** (*required*) - relative path to `PEM` private key for `APNS` certificate issued by Apple. This file have to be somewhere in `priv` directory | ||
* **pool_size** (*required*) - maximum number of used `HTTP/2` connections to google's service | ||
* **mode** (*either `:prod` or `:dev`*) - pool's mode. `REST` client may select pool used to push his notification by specifying matching option in his request | ||
* **endpoint** (*optional*) - URL override for `APNS` service. Useful mainly in tests | ||
* **use_2197** (*optional `true` or `false`*) - whether use alternative port for `APNS`: 2197 | ||
|
||
You may entirely skip the `APNS` config entry to disable `APNS` support. | ||
|
||
## REST API | ||
|
||
### Swagger | ||
|
||
If for some reason you need `Swagger` spec for this `REST` service, after compiling and running this project with `MIX_ENV=dev`, there is swagger endpoint available at `REST` path `/swagger.json` | ||
|
||
### Just tell me what to send already | ||
|
||
There is only one endpoint at this moment: | ||
* `POST /v1/notification/{device_id}` | ||
|
||
As you can imagine, `{device_id}` should be replaced with device ID/Token generated by your push notification provider (`FCM` or `APNS`). The notification should be sent as `JSON` payload of this request. Minimal `JSON` request could be like this: | ||
|
||
```json | ||
{ | ||
"service": "apns", | ||
"body": "notification's text body", | ||
"title": "notification's title" | ||
} | ||
``` | ||
|
||
The full list of options contains the following: | ||
* **service** (*required*, `apns` or `fcm`) - push notifications provider to be used for this notification | ||
* **body** (*required*) - text body of notification | ||
* **title** (*required*) - short title of notification | ||
* **mode** (*optional*, `prod` (default) or `dev`) - allows for selecting named pool configured in `MongoosePush` | ||
* **click_action** (*optional*) - for `FCM` its `activity` to run when notification is clicked. For `APNS` its `category` to invoke. Please refer to Android/iOS documentation for more details about this action | ||
* **tag** (*optional*, `FCM` specific) - notifications aggregation key | ||
* **badge** (*optional*, `APNS` specific) - unread notifications count | ||
* **topic** (*optional*, `APNS` specific) - if APNS certificate configured in `MongoosePush` allows for multiple applications, this field selects the application. Please refer to `APNS` documentation for more datails |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use Mix.Config | ||
|
||
config :maru, MongoosePush.Router, | ||
versioning: [ | ||
using: :path | ||
], | ||
https: [ | ||
ip: {127, 0, 0, 1}, | ||
port: 8443, | ||
keyfile: "priv/ssl/fake_key.pem", | ||
certfile: "priv/ssl/fake_cert.pem", | ||
otp_app: :mongoose_push | ||
] | ||
|
||
config :mongoose_push, fcm: [ | ||
default: [ | ||
key: "fake_app_key", | ||
pool_size: 5, | ||
mode: :prod | ||
] | ||
] | ||
|
||
config :mongoose_push, apns: [ | ||
dev: [ | ||
cert: "priv/apns/dev_cert.pem", | ||
key: "priv/apns/dev_key.pem", | ||
mode: :dev, | ||
use_2197: false, | ||
pool_size: 5 | ||
], | ||
prod: [ | ||
cert: "priv/apns/prod_cert.pem", | ||
key: "priv/apns/prod_key.pem", | ||
mode: :prod, | ||
use_2197: false, | ||
pool_size: 5 | ||
] | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use Mix.Config | ||
|
||
config :maru, MongoosePush.Router, | ||
versioning: [ | ||
using: :path | ||
], | ||
https: [ | ||
ip: {127, 0, 0, 1}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think its a good idea. In many cases this project will be used on same host as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense, thanks for the explanation. |
||
port: 8443, | ||
keyfile: "priv/ssl/fake_key.pem", | ||
certfile: "priv/ssl/fake_cert.pem", | ||
otp_app: :mongoose_push | ||
] | ||
|
||
config :mongoose_push, fcm: [ | ||
prod: [ | ||
key: "fake_app_key", | ||
pool_size: 5, | ||
mode: :prod | ||
] | ||
] | ||
|
||
config :mongoose_push, apns: [ | ||
dev: [ | ||
cert: "priv/apns/dev_cert.pem", | ||
key: "priv/apns/dev_key.pem", | ||
mode: :dev, | ||
use_2197: false, | ||
pool_size: 5 | ||
], | ||
prod: [ | ||
cert: "priv/apns/prod_cert.pem", | ||
key: "priv/apns/prod_key.pem", | ||
mode: :prod, | ||
use_2197: false, | ||
pool_size: 5 | ||
] | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which version of Elixir?