|
| 1 | +# TI Mobile Nodejs Backend |
| 2 | + |
| 3 | + |
| 4 | +## Install software |
| 5 | + |
| 6 | +- node 8.2.0 (v6+ also work) |
| 7 | +- npm 5.x |
| 8 | +- mysql 5.7 |
| 9 | +- a mock SMTP server, e.g. fakeSMTP (http://nilhcem.com/FakeSMTP/) |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +## Configuration |
| 14 | + |
| 15 | +Config is provided at config/default.js and production.js. |
| 16 | + |
| 17 | + |
| 18 | +| key | system Environment name | description | |
| 19 | +| ----------------------------- | ----------------------------- | ---------------------------------------- | |
| 20 | +| LOG_LEVEL | LOG_LEVEL | the log level | |
| 21 | +| PORT | PORT | the server port | |
| 22 | +| PASSWORD_HASH_SALT_LENGTH | PASSWORD_HASH_SALT_LENGTH | the password hash salt length | |
| 23 | +| ACCESS_TOKEN_EXPIRES | ACCESS_TOKEN_EXPIRES | the access token expiration in seconds | |
| 24 | +| VERIFY_TOKEN_EXPIRES | VERIFY_TOKEN_EXPIRES | the verify email token expiration in seconds | |
| 25 | +| FORGOT_PASSWORD_TOKEN_EXPIRES | FORGOT_PASSWORD_TOKEN_EXPIRES | the forgot password token expiration in seconds | |
| 26 | +| QUERY_DEFAULT_LIMIT | QUERY_DEFAULT_LIMIT | the default query limit | |
| 27 | +| API_VERSION | API_VERSION | the API version | |
| 28 | +| VERIFY_EMAIL_SUBJECT | VERIFY_EMAIL_SUBJECT | the verify email subject | |
| 29 | +| VERIFY_EMAIL_CONTENT | VERIFY_EMAIL_CONTENT | the verify email content | |
| 30 | +| FORGOT_PASSWORD_EMAIL_SUBJECT | FORGOT_PASSWORD_EMAIL_SUBJECT | the forgot password email subject | |
| 31 | +| FORGOT_PASSWORD_EMAIL_CONTENT | FORGOT_PASSWORD_EMAIL_CONTENT | the forgot password email content | |
| 32 | +| FROM_EMAIL | FROM_EMAIL | the from email used to send email | |
| 33 | +| email | | the email config used for nodermail | |
| 34 | +| email.host | SMTP_HOST | the SMTP host | |
| 35 | +| email.port | SMTP_PORT | the SMTP port | |
| 36 | +| email.auth.user | SMTP_USER | the SMTP user name | |
| 37 | +| email.auth.pass | SMTP_PASSWORD | the SMTP password | |
| 38 | +| db | | the MySQL db connection object | |
| 39 | +| db.uri | MYSQL_URI | the mysql connect uri , for example "mysql://root:123456@localhost:3306/ti" | |
| 40 | +| db.options | | the mysql connection options | |
| 41 | + |
| 42 | + |
| 43 | + |
| 44 | +## SMTP server setup |
| 45 | + |
| 46 | +We may use a mock SMTP server to simplify tests. And fakeSMTP (http://nilhcem.com/FakeSMTP/) can be used. |
| 47 | +Download the `fakeSMTP-2.0.jar` from the website, then run `java -jar fakeSMTP-2.0.jar -m` to start mock SMTP server. |
| 48 | +When the GUI is shown, cilck the `Start Server` to start the mock SMTP server. |
| 49 | + |
| 50 | +Note that when you view the email content in fakeSMTP, it is raw email content, which is encoded using quoted-printable |
| 51 | +encoding. It is a little different than that is really displayed. At the end of some lines, you may see '=' character, |
| 52 | +this '=' is used to link lines, it is not part of final decoded content. |
| 53 | + |
| 54 | +For example, if you see some token like below: |
| 55 | +``` |
| 56 | +99a12ba0-97a4-43dc-beb2-e4a9886b73= |
| 57 | +b1-1511720563554 |
| 58 | +``` |
| 59 | + |
| 60 | +the actual token should be: |
| 61 | +``` |
| 62 | +99a12ba0-97a4-43dc-beb2-e4a9886b73b1-1511720563554 |
| 63 | +``` |
| 64 | + |
| 65 | + |
| 66 | +Note that the fakeSMTP can accept any username/password. |
| 67 | + |
| 68 | +You may also consider using other SMTP server. |
| 69 | + |
| 70 | +##Heroku deployment |
| 71 | + |
| 72 | +- heroku create |
| 73 | +- git init |
| 74 | +- git add * |
| 75 | +- git commit -m "upload project" |
| 76 | +- heroku addons:create jawsdb |
| 77 | +- heroku config :set EMAIL_USER= [email protected] EMAIL_PASS=123456 SMTP_HOST=smtp.gmail.com SMTP_PORT=465 |
| 78 | +- git push heroku master |
| 79 | + |
| 80 | +## Local deployment |
| 81 | + |
| 82 | +- start MySQL server, create an emtpy database, update config/default.js db.uri to point to the database |
| 83 | +- npm i - install dependencies |
| 84 | +- npm run lint - run code lint check |
| 85 | +- npm run testdata - it will clear all data and insert test data, |
| 86 | + it creates an admin (' [email protected]' / 'password') and normal user (' [email protected]' / 'password') |
| 87 | +- npm start - it will create tables if not present, but if tables are present, it won't change data |
| 88 | + |
| 89 | + |
| 90 | + |
| 91 | +## Verification |
| 92 | + |
| 93 | +- start mock SMTP, start MySQL db, start app as above |
| 94 | +- local Postman collection and environment in the docs folder into Postman |
| 95 | +- do login as admin or user via the `security api` / `login - admin` or `login - user`, after login, the access token will be automatically set |
| 96 | + to environment variable accessToken, and can be used by other API calls; |
| 97 | + please note that some APIs need user role, others need admin role, you may check the routes definitions about which roles are needed for different routes |
| 98 | +- some API depends on other API's data; |
| 99 | + for example, puchase card API needs a card, so you will need to first create a card in Postman, then login as user (purchase API |
| 100 | + needs user role), then purchase it; after purchse, you may get current user data to see that some pointsAmount is cut; |
| 101 | + you may also call the get user cards API to see user's cards |
| 102 | +- you may create a track story, then use progress API to complete its progress, then use progress API to receive rewards, |
| 103 | + then get current user's cards and badges to verify that cards and badge are assigned to user |
| 104 | +- flow to signup user: |
| 105 | + call the signup API; |
| 106 | + in the fakeSMTP, view the last email content, you can see token like below: |
| 107 | +``` |
| 108 | +a0a13351-7192-4151-b4ed-168c25507a= |
| 109 | +ba-1511721439823 |
| 110 | +``` |
| 111 | + the ending '=' should be removed, and the two lines should be linked together, the token is: |
| 112 | +``` |
| 113 | +a0a13351-7192-4151-b4ed-168c25507aba-1511721439823 |
| 114 | +``` |
| 115 | + copy the token to verifyEmail API verificationToken parameter, and call the verifyEmail API |
| 116 | + |
| 117 | +- flow to reset forgot password: |
| 118 | + call the initiateForgotPassword API; |
| 119 | + in the fakeSMTP, view the last email content, you can see token like below: |
| 120 | +``` |
| 121 | +a8181534-05c2-4e51-9da2-27b46f95c98e-1511721790345 |
| 122 | +``` |
| 123 | + copy the token to changeForgotPassword API body forgotPasswordToken parameter, and call the changeForgotPassword API |
| 124 | + |
| 125 | +- other API tests should be intuitive |
| 126 | + |
| 127 | + |
| 128 | + |
| 129 | +## Notes |
| 130 | + |
| 131 | +- see discussion in forum, the app needs to support transaction, so RDBMS (MySQL) should be used instead of MongoDB, MongoDB doesn't support transation. |
| 132 | + Transaction is used when an operation involves multiple db updates. |
| 133 | + For example, when creating/updating TrackStory, multiple child entities are created/updated, |
| 134 | + it is hard to support atomic action if using MongoDB. |
| 135 | + There are other cases when transaction is needed, e.g. purchase card, persisting TrackStoryUserProgress, persisting Achievement, |
| 136 | + receive rewards etc. |
| 137 | + For sequelize transaction management, see: |
| 138 | + http://docs.sequelizejs.com/manual/tutorial/transactions.html#managed-transaction-auto-callback- |
| 139 | +- please take TCUML in precedence over swagger file, the original swagger file has quite some flaws, it is now fixed to sync with the latest APIs; |
| 140 | + but still the TCUML entities/services are more accurate and more thorough, e.g. swagger API request/response may be just part of entities fields. |
| 141 | + I exported two major diagrams (the two PNG files) from TCUML for your reference. |
| 142 | +- for the RacetrackService.search, the given SQL seems not right, I follow the below links to implement it: |
| 143 | + https://gis.stackexchange.com/questions/31628/find-points-within-a-distance-using-mysql |
| 144 | + https://stackoverflow.com/questions/1006654/fastest-way-to-find-distance-between-two-lat-long-points |
| 145 | +- for the RacetrackService.search, raw SQL query is used, so it is important to avoid SQL injection attack, |
| 146 | + helper.sanitize is used to sanitize name filter parameter to avoid SQL injection attack |
| 147 | +- for TrackStory, its child entities are also managed, when creating/updating TrackStory, if a child entity has no id, then the child entity is created, |
| 148 | + otherwise the child entity is updated; |
| 149 | + it is similar for TrackStoryUserProgress and Achievement, their child entities are also managed. |
| 150 | + |
| 151 | + |
| 152 | + |
| 153 | +## Video |
| 154 | + |
| 155 | +https://youtu.be/F1Wiv2c2niY |
| 156 | + |
0 commit comments