|
1 |
| -# coding-test-nic |
| 1 | + |
| 2 | + |
| 3 | +# XKCD test project |
| 4 | + |
| 5 | +XKCD is “A webcomic of romance, sarcasm, math, and language” available at https://xkcd.com. |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +**Figure 1. Example of XKCD comic** |
| 10 | + |
| 11 | +The goal of this test project is to check your Python and JavaScript skills, requiring you to build a site to manage XKCD comics. |
| 12 | + |
| 13 | +XKCD exposes a simple JSON interface, and the details can be seen at https://xkcd.com/json.html. |
| 14 | + |
| 15 | +The site will allow the creation of users, and the users will be able to insert comics’ metadata into a database (PostgreSQL is preferred). |
| 16 | + |
| 17 | +You need to create two projects, one for the backend and one for the frontend. Backend will provide web services that the frontend can consume. |
| 18 | + |
| 19 | +Both projects should contain deployment instructions (Heroku or Docker based deployments are a bonus). You will provide the code for both projects, forking the original repository. That means you will create two forks (backend and frontend). |
| 20 | + |
| 21 | +Description of backend models and web services as follows (a “*” next to a name means that is required). All bodies and responses must be JSON documents, unless something else is said. |
| 22 | + |
| 23 | +The examples contain MongoDB-like ids, but it is not mandatory to follow that. Numeric ids are also accepted. |
| 24 | + |
| 25 | +## User model |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | +Methods to be implemented: |
| 30 | + |
| 31 | +**POST /user** |
| 32 | + |
| 33 | +Creates or updates a user. |
| 34 | + |
| 35 | +The password is passed as plain text but must be encrypted when inserted into the database (bcrypt preferred). |
| 36 | + |
| 37 | + - Example of body: |
| 38 | + |
| 39 | +`{ |
| 40 | + "first_name": "Mike", |
| 41 | + "last_name": "Patterson", |
| 42 | + "email": "something@mail.com", |
| 43 | + "password": "secret123" |
| 44 | +}` |
| 45 | + |
| 46 | + - Example of response: |
| 47 | + |
| 48 | +`{ |
| 49 | + "status": "200", |
| 50 | + "message": "The user was created successfully", |
| 51 | + "id": "558d6da078fea511752289bd" |
| 52 | +}` |
| 53 | + |
| 54 | +When a user is updated the id is required and any parameter can be updated (the id cannot be updated). |
| 55 | + |
| 56 | + - Example of body: |
| 57 | + |
| 58 | +`{ |
| 59 | + "id": "558d6da078fea511752289bd", |
| 60 | + "first_name": "Mike", |
| 61 | + "last_name": "Patterson", |
| 62 | + "email": "something_different@mail.com", |
| 63 | + "password": "secret123" |
| 64 | +}` |
| 65 | + |
| 66 | + - Example of response: |
| 67 | + |
| 68 | +`{ |
| 69 | + "status": "200", |
| 70 | + "message": "The user was updated successfully", |
| 71 | + "id": "558d6da078fea511752289bd" |
| 72 | +}` |
| 73 | + |
| 74 | + |
| 75 | + - Example of body: |
| 76 | + |
| 77 | +`{ |
| 78 | + "id": "558d6da078fea511752289bd", |
| 79 | + "first_name": "Mike", |
| 80 | + "last_name": "Morris" |
| 81 | +}` |
| 82 | + |
| 83 | + - Example of response: |
| 84 | + |
| 85 | +`{ |
| 86 | + "status": "200", |
| 87 | + "message": "The user was updated successfully", |
| 88 | + "id": "558d6da078fea511752289bd" |
| 89 | +}` |
| 90 | + |
| 91 | +Will return status different than 200 in case of errors: |
| 92 | + |
| 93 | + - Examples: |
| 94 | + |
| 95 | +`{ |
| 96 | + "status": "400", |
| 97 | + "message": "User with that email already exists" |
| 98 | +}` |
| 99 | +`{ |
| 100 | + "status": "500", |
| 101 | + "message": "Server error" |
| 102 | +}` |
| 103 | + |
| 104 | +**POST /user/login** |
| 105 | + |
| 106 | +Logs user into the system |
| 107 | + |
| 108 | +Successful login. |
| 109 | + |
| 110 | + - Example of body: |
| 111 | + |
| 112 | +`{ |
| 113 | + "email": "something@mail.com", |
| 114 | + "password": "secret123" |
| 115 | +}` |
| 116 | + |
| 117 | + - Example of response: |
| 118 | + |
| 119 | +`{ |
| 120 | + "status": "200", |
| 121 | + "message": "User logged in successfully" |
| 122 | +}` |
| 123 | + |
| 124 | +Failed login. |
| 125 | + |
| 126 | + - Example of body: |
| 127 | + |
| 128 | +`{ |
| 129 | + "email": "something@mail.com", |
| 130 | + "password": "badpassw0rd" |
| 131 | +}` |
| 132 | + |
| 133 | + - Example of response: |
| 134 | + |
| 135 | +`{ |
| 136 | + "status": "401", |
| 137 | + "message": "Please check your credentials" |
| 138 | +}` |
| 139 | + |
| 140 | +**POST /user/logout** |
| 141 | + |
| 142 | +Logs out current logged in user session |
| 143 | + |
| 144 | +Successful request. |
| 145 | + |
| 146 | + - Example of body: |
| 147 | + |
| 148 | +No parameters |
| 149 | + |
| 150 | + - Example of response: |
| 151 | + |
| 152 | +`{ |
| 153 | + "status": "200", |
| 154 | + "message": "User logged out successfully" |
| 155 | +}` |
| 156 | + |
| 157 | +## Comic model |
| 158 | + |
| 159 | + |
| 160 | + |
| 161 | +Methods to be implemented: |
| 162 | + |
| 163 | +**POST /comic** |
| 164 | + |
| 165 | +Creates or updates a comic |
| 166 | + |
| 167 | + - Example of body: |
| 168 | + |
| 169 | +`{ |
| 170 | + "month": "6", |
| 171 | + "num": 111, |
| 172 | + "link": "", |
| 173 | + "year": 2006, |
| 174 | + "news": "", |
| 175 | + "safe_title": "Firefox and Witchcraft - The Connection?", |
| 176 | + "transcript": "membership in wicca\ntotal firefox downloads\n[[positive slope graph]]\n[[Internet Explorer icon]]\nKeep the Faith\n[[Outline of a cross]]", |
| 177 | + "alt": "ThisadpaidforbythecounciltopromoteMicrosoftandChristianity. Remember, The Bible is Closed Source.", |
| 178 | + "img": "https://imgs.xkcd.com/comics/firefox_wicca.png", |
| 179 | + "title": "Firefox and Witchcraft - The Connection?", |
| 180 | + "day": "5" |
| 181 | +}` |
| 182 | + |
| 183 | + - Example of response: |
| 184 | + |
| 185 | +`{ |
| 186 | + "status": "200", |
| 187 | + "message": "The comic was created successfully", |
| 188 | + "id": "5a453cfd99b423000bc1d554" |
| 189 | +}` |
| 190 | + |
| 191 | + |
| 192 | + - Example of body: |
| 193 | + |
| 194 | +`{ |
| 195 | + "id": "5a453cfd99b423000bc1d554", |
| 196 | + "month": "6", |
| 197 | + "num": 111, |
| 198 | + "link": "", |
| 199 | + "year": 2006, |
| 200 | + "news": "", |
| 201 | + "safe_title": "Firefox and Witchcraft - The Connection? (Updated)", |
| 202 | + "transcript": "membership in wicca\ntotal firefox downloads\n[[positive slope graph]]\n[[Internet Explorer icon]]\nKeep the Faith\n[[Outline of a cross]]", |
| 203 | + "alt": "ThisadpaidforbythecounciltopromoteMicrosoftandChristianity. Remember, The Bible is Closed Source.", |
| 204 | + "img": "https://imgs.xkcd.com/comics/firefox_wicca.png", |
| 205 | + "title": "Firefox and Witchcraft - The Connection? (Updated)", |
| 206 | + "day": "5" |
| 207 | +}` |
| 208 | + |
| 209 | + - Example of response: |
| 210 | + |
| 211 | +`{ |
| 212 | + "status": "200", |
| 213 | + "message": "The comic was updated successfully", |
| 214 | + "id": "5a453cfd99b423000bc1d554" |
| 215 | +}` |
| 216 | + |
| 217 | +**GET /comic/?tag=<query>** |
| 218 | + |
| 219 | +Returns multiple comics which match the tag parameter, as a case insensitive search in the safe_title and transcript fields. The tag can have whitespace between words. It returns an empty document in case there are no matches. |
| 220 | + |
| 221 | + - Example of query: |
| 222 | + |
| 223 | +**GET /comic/?tag=firefox** |
| 224 | + |
| 225 | + - Example of response: |
| 226 | + |
| 227 | +`[ |
| 228 | + { |
| 229 | + "id": "5a453cfd99b423000bc1d555", |
| 230 | + "month": "6", |
| 231 | + "num": 111, |
| 232 | + "link": "", |
| 233 | + "year": 2006, |
| 234 | + "news": "", |
| 235 | + "safe_title": "Firefox and Witchcraft - The Connection?", |
| 236 | + "transcript": "membership in wicca\ntotal firefox downloads\n[[positive slope graph]]\n[[Internet Explorer icon]]\nKeep the Faith\n[[Outline of a cross]]", |
| 237 | + "alt": "ThisadpaidforbythecounciltopromoteMicrosoftandChristianity. Remember, The Bible is Closed Source.", |
| 238 | + "img": "https://imgs.xkcd.com/comics/firefox_wicca.png", |
| 239 | + "title": "Firefox and Witchcraft - The Connection?", |
| 240 | + "day": "5" |
| 241 | + }, |
| 242 | + { |
| 243 | + "id": "5a453cfd99b423000bc1d556", |
| 244 | + "month": "12", |
| 245 | + "num": 1045, |
| 246 | + "link": "", |
| 247 | + "year": 2008, |
| 248 | + "news": "", |
| 249 | + "safe_title": "Web Browsers", |
| 250 | + "transcript": "this is just an example of Chrome and Firefox", |
| 251 | + "title": "Chrome and Firefox", |
| 252 | + "day": "23" |
| 253 | + } |
| 254 | +]` |
| 255 | + |
| 256 | +****DELETE /comic/<comic_id>**** |
| 257 | + |
| 258 | +Deletes a comic using an id. |
| 259 | + |
| 260 | + - Example of query: |
| 261 | + |
| 262 | +**DELETE /comic/5a453cfd99b423000bc1d556** |
| 263 | + |
| 264 | + - Example of response: |
| 265 | + |
| 266 | +`{ |
| 267 | + "status": "200", |
| 268 | + "message": "The comic was deleted successfully", |
| 269 | + "id": "5a453cfd99b423000bc1d556" |
| 270 | +}` |
| 271 | + |
| 272 | + |
| 273 | +## Final notes |
| 274 | + |
| 275 | +Not all methods should require authentication, only actions that require creating something in the database should have it (this includes session management). |
| 276 | + |
| 277 | +You are free to design the frontend site as you wish, but at least it should be able to show the comics as images in case the user performs a query (Angular is preferred). |
| 278 | + |
| 279 | +Please send a pull request against the master branch of the upstream repository once you finish the implementation. |
0 commit comments