A music player that connects to your cloud/distributed storage.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #43 from icidasset/authentication

Refactor Authentication

authored by

Steven Vandevelde and committed by
GitHub
9e90cf62 a7786add

+1580 -550
+1
elm-package.json
··· 16 16 "elm-community/list-extra": "6.1.0 <= v < 7.0.0", 17 17 "elm-community/material-icons": "1.1.0 <= v < 2.0.0", 18 18 "elm-community/maybe-extra": "4.0.0 <= v < 5.0.0", 19 + "elm-community/string-extra": "1.4.0 <= v < 2.0.0", 19 20 "elm-lang/core": "5.1.1 <= v < 6.0.0", 20 21 "elm-lang/dom": "1.1.1 <= v < 2.0.0", 21 22 "elm-lang/html": "2.0.0 <= v < 3.0.0",
+914
package-lock.json
··· 850 850 "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", 851 851 "dev": true 852 852 }, 853 + "camelcase": { 854 + "version": "4.1.0", 855 + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", 856 + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" 857 + }, 853 858 "caniuse-lite": { 854 859 "version": "1.0.30000726", 855 860 "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000726.tgz", ··· 4866 4871 "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 4867 4872 "dev": true 4868 4873 }, 4874 + "nan": { 4875 + "version": "2.7.0", 4876 + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", 4877 + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=", 4878 + "dev": true, 4879 + "optional": true 4880 + }, 4869 4881 "natives": { 4870 4882 "version": "1.1.0", 4871 4883 "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", ··· 5306 5318 "requires": { 5307 5319 "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz", 5308 5320 "async-each": "http://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", 5321 + "fsevents": "1.1.2", 5309 5322 "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", 5310 5323 "inherits": "http://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 5311 5324 "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", 5312 5325 "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", 5313 5326 "path-is-absolute": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 5314 5327 "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" 5328 + }, 5329 + "dependencies": { 5330 + "fsevents": { 5331 + "version": "1.1.2", 5332 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", 5333 + "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", 5334 + "dev": true, 5335 + "optional": true, 5336 + "requires": { 5337 + "nan": "2.7.0", 5338 + "node-pre-gyp": "0.6.36" 5339 + }, 5340 + "dependencies": { 5341 + "abbrev": { 5342 + "version": "1.1.0", 5343 + "bundled": true, 5344 + "dev": true, 5345 + "optional": true 5346 + }, 5347 + "ajv": { 5348 + "version": "4.11.8", 5349 + "bundled": true, 5350 + "dev": true, 5351 + "optional": true, 5352 + "requires": { 5353 + "co": "4.6.0", 5354 + "json-stable-stringify": "1.0.1" 5355 + } 5356 + }, 5357 + "ansi-regex": { 5358 + "version": "2.1.1", 5359 + "bundled": true, 5360 + "dev": true 5361 + }, 5362 + "aproba": { 5363 + "version": "1.1.1", 5364 + "bundled": true, 5365 + "dev": true, 5366 + "optional": true 5367 + }, 5368 + "are-we-there-yet": { 5369 + "version": "1.1.4", 5370 + "bundled": true, 5371 + "dev": true, 5372 + "optional": true, 5373 + "requires": { 5374 + "delegates": "1.0.0", 5375 + "readable-stream": "2.2.9" 5376 + } 5377 + }, 5378 + "asn1": { 5379 + "version": "0.2.3", 5380 + "bundled": true, 5381 + "dev": true, 5382 + "optional": true 5383 + }, 5384 + "assert-plus": { 5385 + "version": "0.2.0", 5386 + "bundled": true, 5387 + "dev": true, 5388 + "optional": true 5389 + }, 5390 + "asynckit": { 5391 + "version": "0.4.0", 5392 + "bundled": true, 5393 + "dev": true, 5394 + "optional": true 5395 + }, 5396 + "aws-sign2": { 5397 + "version": "0.6.0", 5398 + "bundled": true, 5399 + "dev": true, 5400 + "optional": true 5401 + }, 5402 + "aws4": { 5403 + "version": "1.6.0", 5404 + "bundled": true, 5405 + "dev": true, 5406 + "optional": true 5407 + }, 5408 + "balanced-match": { 5409 + "version": "0.4.2", 5410 + "bundled": true, 5411 + "dev": true 5412 + }, 5413 + "bcrypt-pbkdf": { 5414 + "version": "1.0.1", 5415 + "bundled": true, 5416 + "dev": true, 5417 + "optional": true, 5418 + "requires": { 5419 + "tweetnacl": "0.14.5" 5420 + } 5421 + }, 5422 + "block-stream": { 5423 + "version": "0.0.9", 5424 + "bundled": true, 5425 + "dev": true, 5426 + "requires": { 5427 + "inherits": "2.0.3" 5428 + } 5429 + }, 5430 + "boom": { 5431 + "version": "2.10.1", 5432 + "bundled": true, 5433 + "dev": true, 5434 + "requires": { 5435 + "hoek": "2.16.3" 5436 + } 5437 + }, 5438 + "brace-expansion": { 5439 + "version": "1.1.7", 5440 + "bundled": true, 5441 + "dev": true, 5442 + "requires": { 5443 + "balanced-match": "0.4.2", 5444 + "concat-map": "0.0.1" 5445 + } 5446 + }, 5447 + "buffer-shims": { 5448 + "version": "1.0.0", 5449 + "bundled": true, 5450 + "dev": true 5451 + }, 5452 + "caseless": { 5453 + "version": "0.12.0", 5454 + "bundled": true, 5455 + "dev": true, 5456 + "optional": true 5457 + }, 5458 + "co": { 5459 + "version": "4.6.0", 5460 + "bundled": true, 5461 + "dev": true, 5462 + "optional": true 5463 + }, 5464 + "code-point-at": { 5465 + "version": "1.1.0", 5466 + "bundled": true, 5467 + "dev": true 5468 + }, 5469 + "combined-stream": { 5470 + "version": "1.0.5", 5471 + "bundled": true, 5472 + "dev": true, 5473 + "requires": { 5474 + "delayed-stream": "1.0.0" 5475 + } 5476 + }, 5477 + "concat-map": { 5478 + "version": "0.0.1", 5479 + "bundled": true, 5480 + "dev": true 5481 + }, 5482 + "console-control-strings": { 5483 + "version": "1.1.0", 5484 + "bundled": true, 5485 + "dev": true 5486 + }, 5487 + "core-util-is": { 5488 + "version": "1.0.2", 5489 + "bundled": true, 5490 + "dev": true 5491 + }, 5492 + "cryptiles": { 5493 + "version": "2.0.5", 5494 + "bundled": true, 5495 + "dev": true, 5496 + "optional": true, 5497 + "requires": { 5498 + "boom": "2.10.1" 5499 + } 5500 + }, 5501 + "dashdash": { 5502 + "version": "1.14.1", 5503 + "bundled": true, 5504 + "dev": true, 5505 + "optional": true, 5506 + "requires": { 5507 + "assert-plus": "1.0.0" 5508 + }, 5509 + "dependencies": { 5510 + "assert-plus": { 5511 + "version": "1.0.0", 5512 + "bundled": true, 5513 + "dev": true, 5514 + "optional": true 5515 + } 5516 + } 5517 + }, 5518 + "debug": { 5519 + "version": "2.6.8", 5520 + "bundled": true, 5521 + "dev": true, 5522 + "optional": true, 5523 + "requires": { 5524 + "ms": "2.0.0" 5525 + } 5526 + }, 5527 + "deep-extend": { 5528 + "version": "0.4.2", 5529 + "bundled": true, 5530 + "dev": true, 5531 + "optional": true 5532 + }, 5533 + "delayed-stream": { 5534 + "version": "1.0.0", 5535 + "bundled": true, 5536 + "dev": true 5537 + }, 5538 + "delegates": { 5539 + "version": "1.0.0", 5540 + "bundled": true, 5541 + "dev": true, 5542 + "optional": true 5543 + }, 5544 + "ecc-jsbn": { 5545 + "version": "0.1.1", 5546 + "bundled": true, 5547 + "dev": true, 5548 + "optional": true, 5549 + "requires": { 5550 + "jsbn": "0.1.1" 5551 + } 5552 + }, 5553 + "extend": { 5554 + "version": "3.0.1", 5555 + "bundled": true, 5556 + "dev": true, 5557 + "optional": true 5558 + }, 5559 + "extsprintf": { 5560 + "version": "1.0.2", 5561 + "bundled": true, 5562 + "dev": true 5563 + }, 5564 + "forever-agent": { 5565 + "version": "0.6.1", 5566 + "bundled": true, 5567 + "dev": true, 5568 + "optional": true 5569 + }, 5570 + "form-data": { 5571 + "version": "2.1.4", 5572 + "bundled": true, 5573 + "dev": true, 5574 + "optional": true, 5575 + "requires": { 5576 + "asynckit": "0.4.0", 5577 + "combined-stream": "1.0.5", 5578 + "mime-types": "2.1.15" 5579 + } 5580 + }, 5581 + "fs.realpath": { 5582 + "version": "1.0.0", 5583 + "bundled": true, 5584 + "dev": true 5585 + }, 5586 + "fstream": { 5587 + "version": "1.0.11", 5588 + "bundled": true, 5589 + "dev": true, 5590 + "requires": { 5591 + "graceful-fs": "4.1.11", 5592 + "inherits": "2.0.3", 5593 + "mkdirp": "0.5.1", 5594 + "rimraf": "2.6.1" 5595 + } 5596 + }, 5597 + "fstream-ignore": { 5598 + "version": "1.0.5", 5599 + "bundled": true, 5600 + "dev": true, 5601 + "optional": true, 5602 + "requires": { 5603 + "fstream": "1.0.11", 5604 + "inherits": "2.0.3", 5605 + "minimatch": "3.0.4" 5606 + } 5607 + }, 5608 + "gauge": { 5609 + "version": "2.7.4", 5610 + "bundled": true, 5611 + "dev": true, 5612 + "optional": true, 5613 + "requires": { 5614 + "aproba": "1.1.1", 5615 + "console-control-strings": "1.1.0", 5616 + "has-unicode": "2.0.1", 5617 + "object-assign": "4.1.1", 5618 + "signal-exit": "3.0.2", 5619 + "string-width": "1.0.2", 5620 + "strip-ansi": "3.0.1", 5621 + "wide-align": "1.1.2" 5622 + } 5623 + }, 5624 + "getpass": { 5625 + "version": "0.1.7", 5626 + "bundled": true, 5627 + "dev": true, 5628 + "optional": true, 5629 + "requires": { 5630 + "assert-plus": "1.0.0" 5631 + }, 5632 + "dependencies": { 5633 + "assert-plus": { 5634 + "version": "1.0.0", 5635 + "bundled": true, 5636 + "dev": true, 5637 + "optional": true 5638 + } 5639 + } 5640 + }, 5641 + "glob": { 5642 + "version": "7.1.2", 5643 + "bundled": true, 5644 + "dev": true, 5645 + "requires": { 5646 + "fs.realpath": "1.0.0", 5647 + "inflight": "1.0.6", 5648 + "inherits": "2.0.3", 5649 + "minimatch": "3.0.4", 5650 + "once": "1.4.0", 5651 + "path-is-absolute": "1.0.1" 5652 + } 5653 + }, 5654 + "graceful-fs": { 5655 + "version": "4.1.11", 5656 + "bundled": true, 5657 + "dev": true 5658 + }, 5659 + "har-schema": { 5660 + "version": "1.0.5", 5661 + "bundled": true, 5662 + "dev": true, 5663 + "optional": true 5664 + }, 5665 + "har-validator": { 5666 + "version": "4.2.1", 5667 + "bundled": true, 5668 + "dev": true, 5669 + "optional": true, 5670 + "requires": { 5671 + "ajv": "4.11.8", 5672 + "har-schema": "1.0.5" 5673 + } 5674 + }, 5675 + "has-unicode": { 5676 + "version": "2.0.1", 5677 + "bundled": true, 5678 + "dev": true, 5679 + "optional": true 5680 + }, 5681 + "hawk": { 5682 + "version": "3.1.3", 5683 + "bundled": true, 5684 + "dev": true, 5685 + "optional": true, 5686 + "requires": { 5687 + "boom": "2.10.1", 5688 + "cryptiles": "2.0.5", 5689 + "hoek": "2.16.3", 5690 + "sntp": "1.0.9" 5691 + } 5692 + }, 5693 + "hoek": { 5694 + "version": "2.16.3", 5695 + "bundled": true, 5696 + "dev": true 5697 + }, 5698 + "http-signature": { 5699 + "version": "1.1.1", 5700 + "bundled": true, 5701 + "dev": true, 5702 + "optional": true, 5703 + "requires": { 5704 + "assert-plus": "0.2.0", 5705 + "jsprim": "1.4.0", 5706 + "sshpk": "1.13.0" 5707 + } 5708 + }, 5709 + "inflight": { 5710 + "version": "1.0.6", 5711 + "bundled": true, 5712 + "dev": true, 5713 + "requires": { 5714 + "once": "1.4.0", 5715 + "wrappy": "1.0.2" 5716 + } 5717 + }, 5718 + "inherits": { 5719 + "version": "2.0.3", 5720 + "bundled": true, 5721 + "dev": true 5722 + }, 5723 + "ini": { 5724 + "version": "1.3.4", 5725 + "bundled": true, 5726 + "dev": true, 5727 + "optional": true 5728 + }, 5729 + "is-fullwidth-code-point": { 5730 + "version": "1.0.0", 5731 + "bundled": true, 5732 + "dev": true, 5733 + "requires": { 5734 + "number-is-nan": "1.0.1" 5735 + } 5736 + }, 5737 + "is-typedarray": { 5738 + "version": "1.0.0", 5739 + "bundled": true, 5740 + "dev": true, 5741 + "optional": true 5742 + }, 5743 + "isarray": { 5744 + "version": "1.0.0", 5745 + "bundled": true, 5746 + "dev": true 5747 + }, 5748 + "isstream": { 5749 + "version": "0.1.2", 5750 + "bundled": true, 5751 + "dev": true, 5752 + "optional": true 5753 + }, 5754 + "jodid25519": { 5755 + "version": "1.0.2", 5756 + "bundled": true, 5757 + "dev": true, 5758 + "optional": true, 5759 + "requires": { 5760 + "jsbn": "0.1.1" 5761 + } 5762 + }, 5763 + "jsbn": { 5764 + "version": "0.1.1", 5765 + "bundled": true, 5766 + "dev": true, 5767 + "optional": true 5768 + }, 5769 + "json-schema": { 5770 + "version": "0.2.3", 5771 + "bundled": true, 5772 + "dev": true, 5773 + "optional": true 5774 + }, 5775 + "json-stable-stringify": { 5776 + "version": "1.0.1", 5777 + "bundled": true, 5778 + "dev": true, 5779 + "optional": true, 5780 + "requires": { 5781 + "jsonify": "0.0.0" 5782 + } 5783 + }, 5784 + "json-stringify-safe": { 5785 + "version": "5.0.1", 5786 + "bundled": true, 5787 + "dev": true, 5788 + "optional": true 5789 + }, 5790 + "jsonify": { 5791 + "version": "0.0.0", 5792 + "bundled": true, 5793 + "dev": true, 5794 + "optional": true 5795 + }, 5796 + "jsprim": { 5797 + "version": "1.4.0", 5798 + "bundled": true, 5799 + "dev": true, 5800 + "optional": true, 5801 + "requires": { 5802 + "assert-plus": "1.0.0", 5803 + "extsprintf": "1.0.2", 5804 + "json-schema": "0.2.3", 5805 + "verror": "1.3.6" 5806 + }, 5807 + "dependencies": { 5808 + "assert-plus": { 5809 + "version": "1.0.0", 5810 + "bundled": true, 5811 + "dev": true, 5812 + "optional": true 5813 + } 5814 + } 5815 + }, 5816 + "mime-db": { 5817 + "version": "1.27.0", 5818 + "bundled": true, 5819 + "dev": true 5820 + }, 5821 + "mime-types": { 5822 + "version": "2.1.15", 5823 + "bundled": true, 5824 + "dev": true, 5825 + "requires": { 5826 + "mime-db": "1.27.0" 5827 + } 5828 + }, 5829 + "minimatch": { 5830 + "version": "3.0.4", 5831 + "bundled": true, 5832 + "dev": true, 5833 + "requires": { 5834 + "brace-expansion": "1.1.7" 5835 + } 5836 + }, 5837 + "minimist": { 5838 + "version": "0.0.8", 5839 + "bundled": true, 5840 + "dev": true 5841 + }, 5842 + "mkdirp": { 5843 + "version": "0.5.1", 5844 + "bundled": true, 5845 + "dev": true, 5846 + "requires": { 5847 + "minimist": "0.0.8" 5848 + } 5849 + }, 5850 + "ms": { 5851 + "version": "2.0.0", 5852 + "bundled": true, 5853 + "dev": true, 5854 + "optional": true 5855 + }, 5856 + "node-pre-gyp": { 5857 + "version": "0.6.36", 5858 + "bundled": true, 5859 + "dev": true, 5860 + "optional": true, 5861 + "requires": { 5862 + "mkdirp": "0.5.1", 5863 + "nopt": "4.0.1", 5864 + "npmlog": "4.1.0", 5865 + "rc": "1.2.1", 5866 + "request": "2.81.0", 5867 + "rimraf": "2.6.1", 5868 + "semver": "5.3.0", 5869 + "tar": "2.2.1", 5870 + "tar-pack": "3.4.0" 5871 + } 5872 + }, 5873 + "nopt": { 5874 + "version": "4.0.1", 5875 + "bundled": true, 5876 + "dev": true, 5877 + "optional": true, 5878 + "requires": { 5879 + "abbrev": "1.1.0", 5880 + "osenv": "0.1.4" 5881 + } 5882 + }, 5883 + "npmlog": { 5884 + "version": "4.1.0", 5885 + "bundled": true, 5886 + "dev": true, 5887 + "optional": true, 5888 + "requires": { 5889 + "are-we-there-yet": "1.1.4", 5890 + "console-control-strings": "1.1.0", 5891 + "gauge": "2.7.4", 5892 + "set-blocking": "2.0.0" 5893 + } 5894 + }, 5895 + "number-is-nan": { 5896 + "version": "1.0.1", 5897 + "bundled": true, 5898 + "dev": true 5899 + }, 5900 + "oauth-sign": { 5901 + "version": "0.8.2", 5902 + "bundled": true, 5903 + "dev": true, 5904 + "optional": true 5905 + }, 5906 + "object-assign": { 5907 + "version": "4.1.1", 5908 + "bundled": true, 5909 + "dev": true, 5910 + "optional": true 5911 + }, 5912 + "once": { 5913 + "version": "1.4.0", 5914 + "bundled": true, 5915 + "dev": true, 5916 + "requires": { 5917 + "wrappy": "1.0.2" 5918 + } 5919 + }, 5920 + "os-homedir": { 5921 + "version": "1.0.2", 5922 + "bundled": true, 5923 + "dev": true, 5924 + "optional": true 5925 + }, 5926 + "os-tmpdir": { 5927 + "version": "1.0.2", 5928 + "bundled": true, 5929 + "dev": true, 5930 + "optional": true 5931 + }, 5932 + "osenv": { 5933 + "version": "0.1.4", 5934 + "bundled": true, 5935 + "dev": true, 5936 + "optional": true, 5937 + "requires": { 5938 + "os-homedir": "1.0.2", 5939 + "os-tmpdir": "1.0.2" 5940 + } 5941 + }, 5942 + "path-is-absolute": { 5943 + "version": "1.0.1", 5944 + "bundled": true, 5945 + "dev": true 5946 + }, 5947 + "performance-now": { 5948 + "version": "0.2.0", 5949 + "bundled": true, 5950 + "dev": true, 5951 + "optional": true 5952 + }, 5953 + "process-nextick-args": { 5954 + "version": "1.0.7", 5955 + "bundled": true, 5956 + "dev": true 5957 + }, 5958 + "punycode": { 5959 + "version": "1.4.1", 5960 + "bundled": true, 5961 + "dev": true, 5962 + "optional": true 5963 + }, 5964 + "qs": { 5965 + "version": "6.4.0", 5966 + "bundled": true, 5967 + "dev": true, 5968 + "optional": true 5969 + }, 5970 + "rc": { 5971 + "version": "1.2.1", 5972 + "bundled": true, 5973 + "dev": true, 5974 + "optional": true, 5975 + "requires": { 5976 + "deep-extend": "0.4.2", 5977 + "ini": "1.3.4", 5978 + "minimist": "1.2.0", 5979 + "strip-json-comments": "2.0.1" 5980 + }, 5981 + "dependencies": { 5982 + "minimist": { 5983 + "version": "1.2.0", 5984 + "bundled": true, 5985 + "dev": true, 5986 + "optional": true 5987 + } 5988 + } 5989 + }, 5990 + "readable-stream": { 5991 + "version": "2.2.9", 5992 + "bundled": true, 5993 + "dev": true, 5994 + "requires": { 5995 + "buffer-shims": "1.0.0", 5996 + "core-util-is": "1.0.2", 5997 + "inherits": "2.0.3", 5998 + "isarray": "1.0.0", 5999 + "process-nextick-args": "1.0.7", 6000 + "string_decoder": "1.0.1", 6001 + "util-deprecate": "1.0.2" 6002 + } 6003 + }, 6004 + "request": { 6005 + "version": "2.81.0", 6006 + "bundled": true, 6007 + "dev": true, 6008 + "optional": true, 6009 + "requires": { 6010 + "aws-sign2": "0.6.0", 6011 + "aws4": "1.6.0", 6012 + "caseless": "0.12.0", 6013 + "combined-stream": "1.0.5", 6014 + "extend": "3.0.1", 6015 + "forever-agent": "0.6.1", 6016 + "form-data": "2.1.4", 6017 + "har-validator": "4.2.1", 6018 + "hawk": "3.1.3", 6019 + "http-signature": "1.1.1", 6020 + "is-typedarray": "1.0.0", 6021 + "isstream": "0.1.2", 6022 + "json-stringify-safe": "5.0.1", 6023 + "mime-types": "2.1.15", 6024 + "oauth-sign": "0.8.2", 6025 + "performance-now": "0.2.0", 6026 + "qs": "6.4.0", 6027 + "safe-buffer": "5.0.1", 6028 + "stringstream": "0.0.5", 6029 + "tough-cookie": "2.3.2", 6030 + "tunnel-agent": "0.6.0", 6031 + "uuid": "3.0.1" 6032 + } 6033 + }, 6034 + "rimraf": { 6035 + "version": "2.6.1", 6036 + "bundled": true, 6037 + "dev": true, 6038 + "requires": { 6039 + "glob": "7.1.2" 6040 + } 6041 + }, 6042 + "safe-buffer": { 6043 + "version": "5.0.1", 6044 + "bundled": true, 6045 + "dev": true 6046 + }, 6047 + "semver": { 6048 + "version": "5.3.0", 6049 + "bundled": true, 6050 + "dev": true, 6051 + "optional": true 6052 + }, 6053 + "set-blocking": { 6054 + "version": "2.0.0", 6055 + "bundled": true, 6056 + "dev": true, 6057 + "optional": true 6058 + }, 6059 + "signal-exit": { 6060 + "version": "3.0.2", 6061 + "bundled": true, 6062 + "dev": true, 6063 + "optional": true 6064 + }, 6065 + "sntp": { 6066 + "version": "1.0.9", 6067 + "bundled": true, 6068 + "dev": true, 6069 + "optional": true, 6070 + "requires": { 6071 + "hoek": "2.16.3" 6072 + } 6073 + }, 6074 + "sshpk": { 6075 + "version": "1.13.0", 6076 + "bundled": true, 6077 + "dev": true, 6078 + "optional": true, 6079 + "requires": { 6080 + "asn1": "0.2.3", 6081 + "assert-plus": "1.0.0", 6082 + "bcrypt-pbkdf": "1.0.1", 6083 + "dashdash": "1.14.1", 6084 + "ecc-jsbn": "0.1.1", 6085 + "getpass": "0.1.7", 6086 + "jodid25519": "1.0.2", 6087 + "jsbn": "0.1.1", 6088 + "tweetnacl": "0.14.5" 6089 + }, 6090 + "dependencies": { 6091 + "assert-plus": { 6092 + "version": "1.0.0", 6093 + "bundled": true, 6094 + "dev": true, 6095 + "optional": true 6096 + } 6097 + } 6098 + }, 6099 + "string-width": { 6100 + "version": "1.0.2", 6101 + "bundled": true, 6102 + "dev": true, 6103 + "requires": { 6104 + "code-point-at": "1.1.0", 6105 + "is-fullwidth-code-point": "1.0.0", 6106 + "strip-ansi": "3.0.1" 6107 + } 6108 + }, 6109 + "string_decoder": { 6110 + "version": "1.0.1", 6111 + "bundled": true, 6112 + "dev": true, 6113 + "requires": { 6114 + "safe-buffer": "5.0.1" 6115 + } 6116 + }, 6117 + "stringstream": { 6118 + "version": "0.0.5", 6119 + "bundled": true, 6120 + "dev": true, 6121 + "optional": true 6122 + }, 6123 + "strip-ansi": { 6124 + "version": "3.0.1", 6125 + "bundled": true, 6126 + "dev": true, 6127 + "requires": { 6128 + "ansi-regex": "2.1.1" 6129 + } 6130 + }, 6131 + "strip-json-comments": { 6132 + "version": "2.0.1", 6133 + "bundled": true, 6134 + "dev": true, 6135 + "optional": true 6136 + }, 6137 + "tar": { 6138 + "version": "2.2.1", 6139 + "bundled": true, 6140 + "dev": true, 6141 + "requires": { 6142 + "block-stream": "0.0.9", 6143 + "fstream": "1.0.11", 6144 + "inherits": "2.0.3" 6145 + } 6146 + }, 6147 + "tar-pack": { 6148 + "version": "3.4.0", 6149 + "bundled": true, 6150 + "dev": true, 6151 + "optional": true, 6152 + "requires": { 6153 + "debug": "2.6.8", 6154 + "fstream": "1.0.11", 6155 + "fstream-ignore": "1.0.5", 6156 + "once": "1.4.0", 6157 + "readable-stream": "2.2.9", 6158 + "rimraf": "2.6.1", 6159 + "tar": "2.2.1", 6160 + "uid-number": "0.0.6" 6161 + } 6162 + }, 6163 + "tough-cookie": { 6164 + "version": "2.3.2", 6165 + "bundled": true, 6166 + "dev": true, 6167 + "optional": true, 6168 + "requires": { 6169 + "punycode": "1.4.1" 6170 + } 6171 + }, 6172 + "tunnel-agent": { 6173 + "version": "0.6.0", 6174 + "bundled": true, 6175 + "dev": true, 6176 + "optional": true, 6177 + "requires": { 6178 + "safe-buffer": "5.0.1" 6179 + } 6180 + }, 6181 + "tweetnacl": { 6182 + "version": "0.14.5", 6183 + "bundled": true, 6184 + "dev": true, 6185 + "optional": true 6186 + }, 6187 + "uid-number": { 6188 + "version": "0.0.6", 6189 + "bundled": true, 6190 + "dev": true, 6191 + "optional": true 6192 + }, 6193 + "util-deprecate": { 6194 + "version": "1.0.2", 6195 + "bundled": true, 6196 + "dev": true 6197 + }, 6198 + "uuid": { 6199 + "version": "3.0.1", 6200 + "bundled": true, 6201 + "dev": true, 6202 + "optional": true 6203 + }, 6204 + "verror": { 6205 + "version": "1.3.6", 6206 + "bundled": true, 6207 + "dev": true, 6208 + "optional": true, 6209 + "requires": { 6210 + "extsprintf": "1.0.2" 6211 + } 6212 + }, 6213 + "wide-align": { 6214 + "version": "1.1.2", 6215 + "bundled": true, 6216 + "dev": true, 6217 + "optional": true, 6218 + "requires": { 6219 + "string-width": "1.0.2" 6220 + } 6221 + }, 6222 + "wrappy": { 6223 + "version": "1.0.2", 6224 + "bundled": true, 6225 + "dev": true 6226 + } 6227 + } 6228 + } 5315 6229 } 5316 6230 }, 5317 6231 "find-up": {
+1
package.json
··· 13 13 "dependencies": { 14 14 "1-liners": "^0.4.0", 15 15 "blockstack": "^0.10.1", 16 + "camelcase": "^4.1.0", 16 17 "elasticlunr": "^0.9.5", 17 18 "jsmediatags": "^3.8.0", 18 19 "tocca": "^2.0.1"
-164
src/App/Authentication/Method.elm
··· 1 - module Authentication.Method exposing (..) 2 - 3 - import Authentication.Types exposing (..) 4 - import LocalStorage 5 - import Native.Authentication.Blockstack 6 - import Native.Authentication.Local 7 - import Task exposing (Task) 8 - 9 - 10 - -- Constants 11 - 12 - 13 - storageKey : String 14 - storageKey = 15 - "authenticationMethod" 16 - 17 - 18 - type alias Error = 19 - String 20 - 21 - 22 - 23 - -- Actions 24 - 25 - 26 - construct : Method -> Task () () 27 - construct method = 28 - case method of 29 - Blockstack -> 30 - Native.Authentication.Blockstack.construct 31 - 32 - Local -> 33 - Native.Authentication.Local.construct 34 - 35 - 36 - deconstruct : Method -> Task () () 37 - deconstruct method = 38 - case method of 39 - Blockstack -> 40 - Native.Authentication.Blockstack.deconstruct 41 - 42 - Local -> 43 - Native.Authentication.Local.deconstruct 44 - 45 - 46 - isSignedIn : Method -> Task Never Bool 47 - isSignedIn method = 48 - case method of 49 - Blockstack -> 50 - Native.Authentication.Blockstack.isSignedIn 51 - 52 - Local -> 53 - Native.Authentication.Local.isSignedIn 54 - 55 - 56 - isSigningIn : Method -> Task Never Bool 57 - isSigningIn method = 58 - case method of 59 - Blockstack -> 60 - Native.Authentication.Blockstack.isSigningIn 61 - 62 - Local -> 63 - Native.Authentication.Local.isSigningIn 64 - 65 - 66 - handleSignInProcess : Method -> Task Never SignInProcessConsequence 67 - handleSignInProcess method = 68 - case method of 69 - Blockstack -> 70 - Native.Authentication.Blockstack.handleSignInProcess 71 - 72 - Local -> 73 - Native.Authentication.Local.handleSignInProcess 74 - 75 - 76 - signIn : Method -> Task Never SignInConsequence 77 - signIn method = 78 - case method of 79 - Blockstack -> 80 - Native.Authentication.Blockstack.signIn 81 - 82 - Local -> 83 - Native.Authentication.Local.signIn 84 - 85 - 86 - signOut : Method -> Task Never () 87 - signOut method = 88 - case method of 89 - Blockstack -> 90 - Native.Authentication.Blockstack.signOut 91 - 92 - Local -> 93 - Native.Authentication.Local.signOut 94 - 95 - 96 - getData : Method -> Task Error (Maybe String) 97 - getData method = 98 - case method of 99 - Blockstack -> 100 - Native.Authentication.Blockstack.getData 101 - 102 - Local -> 103 - Native.Authentication.Local.getData 104 - 105 - 106 - storeData : Method -> String -> Task Error () 107 - storeData method json = 108 - case method of 109 - Blockstack -> 110 - Native.Authentication.Blockstack.storeData json 111 - 112 - Local -> 113 - Native.Authentication.Local.storeData json 114 - 115 - 116 - 117 - -- Local storage 118 - 119 - 120 - get : Task LocalStorage.Error (Maybe Method) 121 - get = 122 - storageKey 123 - |> LocalStorage.get 124 - |> Task.map (Maybe.map stringToType) 125 - 126 - 127 - set : Method -> Task LocalStorage.Error () 128 - set method = 129 - LocalStorage.set 130 - storageKey 131 - (typeToString method) 132 - 133 - 134 - remove : Task LocalStorage.Error () 135 - remove = 136 - LocalStorage.remove 137 - storageKey 138 - 139 - 140 - 141 - -- Union types & stuff 142 - 143 - 144 - stringToType : String -> Method 145 - stringToType str = 146 - case String.toUpper str of 147 - "BLOCKSTACK" -> 148 - Blockstack 149 - 150 - "LOCAL" -> 151 - Local 152 - 153 - _ -> 154 - Debug.crash "Invalid authentication method" 155 - 156 - 157 - typeToString : Method -> String 158 - typeToString method = 159 - case method of 160 - Blockstack -> 161 - "BLOCKSTACK" 162 - 163 - Local -> 164 - "LOCAL"
+16
src/App/Authentication/Ports.elm
··· 1 + port module Authentication.Ports exposing (..) 2 + 3 + import Authentication.Types exposing (..) 4 + 5 + 6 + -- 💡 7 + 8 + 9 + port authenticationEvent : OutsideEvent -> Cmd msg 10 + 11 + 12 + 13 + -- 🚽 14 + 15 + 16 + port authenticationEventResult : (OutsideEvent -> msg) -> Sub msg
+230 -145
src/App/Authentication/State.elm
··· 1 1 module Authentication.State exposing (..) 2 2 3 - import Authentication.Method 3 + import Authentication.Transformers as Transformers 4 + import Authentication.Ports as Ports 4 5 import Authentication.Types exposing (..) 5 6 import Dict 6 7 import Equalizer.State as Equalizer 7 - import Json.Decode as Decode 8 + import Json.Decode as Decode exposing (..) 8 9 import Json.Encode as Encode 9 10 import Navigation 10 11 import Queue.Ports 11 - import Response.Ext exposing (do, doDelayed) 12 + import Response.Ext exposing (do) 12 13 import Routing.Types exposing (Page(..)) 13 - import Task exposing (Task) 14 - import Time 15 - import Tracks.Encoding 16 - import Tracks.Ports 17 - import Tracks.Types 18 14 import Types as TopLevel 19 15 20 16 ··· 31 27 initialCommands : Cmd TopLevel.Msg 32 28 initialCommands = 33 29 Cmd.batch 34 - [ Task.attempt 35 - (DidGetMethod >> TopLevel.AuthenticationMsg) 36 - (Authentication.Method.get) 37 - ] 30 + [ issue MethodGet ] 38 31 39 32 40 33 ··· 47 40 ------------------------------------ 48 41 -- Step 1 49 42 ------------------------------------ 50 - DidGetMethod (Ok m) -> 51 - (!) 52 - { model | method = m } 53 - [ case m of 54 - Just method -> 55 - Task.attempt 56 - (DidConstruct >> TopLevel.AuthenticationMsg) 57 - (Authentication.Method.construct method) 43 + Incoming MethodGet (Ok result) -> 44 + case decodeValue (maybe string) result of 45 + -- 🚀 46 + -- 47 + Ok (Just m) -> 48 + (!) 49 + { model | method = Just (Transformers.stringToMethod m) } 50 + [ issue Construct ] 58 51 59 - Nothing -> 60 - after 61 - ] 52 + -- First time authenticating, 53 + -- so no data yet. 54 + Ok Nothing -> 55 + (!) 56 + model 57 + [ afterwards ] 62 58 63 - DidGetMethod (Err _) -> 64 - -- Do nothing, the user has not used the application before. 65 - -- So they haven't signed in yet. 66 - (!) 67 - model 68 - [ after ] 59 + -- ⚠️ 60 + -- 61 + Err err -> 62 + handleError model err 63 + 64 + -- 65 + -- Error 66 + -- 67 + Incoming MethodGet (Err err) -> 68 + handleError model err 69 69 70 70 ------------------------------------ 71 71 -- Step 2 72 72 ------------------------------------ 73 - DidConstruct (Ok _) -> 74 - (!) 75 - model 76 - [ case model.method of 77 - Just method -> 78 - Task.perform 79 - (DidGetIsSignedIn >> TopLevel.AuthenticationMsg) 80 - (Authentication.Method.isSignedIn method) 73 + Incoming Construct (Ok _) -> 74 + (!) model [ issue IsSignedIn ] 81 75 82 - Nothing -> 83 - after 84 - ] 85 - 86 - DidConstruct (Err e) -> 87 - (!) 88 - model 89 - [ "Your browser does not support this authentication method" 90 - |> ErrorScreen 91 - |> Routing.Types.SetPage 92 - |> TopLevel.RoutingMsg 93 - |> do 94 - ] 76 + Incoming Construct (Err _) -> 77 + handleError model "Your browser does not support this authentication method" 95 78 96 79 ------------------------------------ 97 80 -- Step 3 98 81 ------------------------------------ 99 - DidGetIsSignedIn isSignedIn -> 100 - (!) 101 - { model | signedIn = isSignedIn } 102 - [ case model.method of 103 - Just method -> 104 - if isSignedIn then 105 - Task.attempt 106 - (DidGetData >> TopLevel.AuthenticationMsg) 107 - (Authentication.Method.getData method) 108 - else 109 - Task.perform 110 - (DidGetIsSigningIn >> TopLevel.AuthenticationMsg) 111 - (Authentication.Method.isSigningIn method) 82 + Incoming IsSignedIn (Ok result) -> 83 + case decodeValue bool result of 84 + -- Yes 85 + -- 86 + Ok True -> 87 + (!) { model | signedIn = True } [ issue GetData ] 112 88 113 - Nothing -> 114 - after 115 - ] 89 + -- No 90 + -- 91 + Ok False -> 92 + (!) { model | signedIn = False } [ issue IsSigningIn ] 93 + 94 + -- ? 95 + -- 96 + Err err -> 97 + handleError model err 98 + 99 + -- 100 + -- Error 101 + -- 102 + Incoming IsSignedIn (Err err) -> 103 + handleError model err 116 104 117 105 ------------------------------------ 118 106 -- Step 4a 119 107 ------------------------------------ 120 - DidGetData (Ok (Just json)) -> 121 - (!) model [ do (TopLevel.ImportUserData json) ] 122 - 123 - DidGetData (Ok Nothing) -> 124 - -- The user has no data yet, 125 - -- so nothing to do here. 126 - (!) model [ after ] 127 - 128 - DidGetData (Err _) -> 108 + Incoming GetData (Ok result) -> 129 109 (!) 130 110 model 131 - [ "Failed to retrieve the data from the selected authentication method" 132 - |> ErrorScreen 133 - |> Routing.Types.SetPage 134 - |> TopLevel.RoutingMsg 135 - |> do 111 + [ case decodeValue (maybe string) result of 112 + Ok (Just json) -> 113 + do (TopLevel.ImportUserData json) 114 + 115 + Ok Nothing -> 116 + afterwards 117 + 118 + Err err -> 119 + displayError err 136 120 ] 137 121 122 + -- 123 + -- Error 124 + -- 125 + Incoming GetData (Err _) -> 126 + handleError 127 + model 128 + "Failed to retrieve the data from the selected authentication method" 129 + 138 130 ------------------------------------ 139 131 -- Step 4b 140 132 ------------------------------------ 141 - DidGetIsSigningIn True -> 133 + Incoming IsSigningIn (Ok result) -> 142 134 (!) 143 135 model 144 - [ case model.method of 145 - Just method -> 146 - Task.perform 147 - (DidHandleSignInProcess >> TopLevel.AuthenticationMsg) 148 - (Authentication.Method.handleSignInProcess method) 136 + [ case decodeValue bool result of 137 + Ok True -> 138 + issue HandleSignInProcess 139 + 140 + Ok False -> 141 + afterwards 149 142 150 - Nothing -> 151 - after 143 + Err err -> 144 + displayError err 152 145 ] 153 146 154 - DidGetIsSigningIn False -> 155 - (!) 156 - model 157 - [ after ] 147 + -- 148 + -- Error 149 + -- 150 + Incoming IsSigningIn (Err err) -> 151 + handleError model err 158 152 159 - DidHandleSignInProcess consequence -> 153 + ------------------------------------ 154 + -- Step 4b.1 155 + ------------------------------------ 156 + Incoming HandleSignInProcess (Ok result) -> 160 157 (!) 161 158 { model | signedIn = True } 162 - [ case consequence of 163 - KeepUrl -> 159 + [ issue GetData 160 + , case decodeValue string result of 161 + Ok "KeepUrl" -> 164 162 Cmd.none 165 163 166 - ModifyUrl -> 164 + Ok "ModifyUrl" -> 167 165 Navigation.modifyUrl "/" 168 - , case model.method of 169 - Just method -> 170 - Task.attempt 171 - (DidGetData >> TopLevel.AuthenticationMsg) 172 - (Authentication.Method.getData method) 173 166 174 - Nothing -> 175 - after 167 + Ok _ -> 168 + displayError "Invalid response from HandleSignInProcess" 169 + 170 + Err err -> 171 + displayError err 176 172 ] 177 173 174 + -- 175 + -- Error 176 + -- 177 + Incoming HandleSignInProcess (Err err) -> 178 + handleError model err 179 + 178 180 ------------------------------------ 179 181 -- Sign in 180 182 ------------------------------------ 181 - SignIn method -> 183 + PerformSignIn method -> 182 184 (!) 183 185 { model | method = Just method } 184 - [ Task.attempt 185 - (always TopLevel.NoOp) 186 - (Authentication.Method.set method) 186 + [ do TopLevel.ShowLoadingScreen 187 187 188 - -- Sign in 189 - , Task.perform 190 - (DidSignIn >> TopLevel.AuthenticationMsg) 191 - (Authentication.Method.signIn method) 192 - 193 - -- Show loading screen 194 - , TopLevel.ShowLoadingScreen 195 - |> do 188 + -- Set method 189 + , method 190 + |> Transformers.methodToString 191 + |> Encode.string 192 + |> issueWithData MethodSet 196 193 ] 197 194 198 - DidSignIn consequence -> 199 - case consequence of 200 - None -> 195 + ------------------------------------ 196 + -- Sign in / Events 197 + ------------------------------------ 198 + Incoming MethodSet (Ok _) -> 199 + (!) model [ issue SignIn ] 200 + 201 + Incoming MethodSet (Err err) -> 202 + handleError model err 203 + 204 + Incoming SignIn (Ok result) -> 205 + -- Handle SignIn consequence 206 + case decodeValue string result of 207 + Ok "None" -> 201 208 (!) 202 209 { model | signedIn = True } 203 - [ case model.method of 204 - Just method -> 205 - Task.attempt 206 - (DidConstruct >> TopLevel.AuthenticationMsg) 207 - (Authentication.Method.construct method) 210 + [ issue Construct ] 208 211 209 - Nothing -> 210 - Cmd.none 211 - ] 212 + Ok "Redirect" -> 213 + (!) 214 + model 215 + [] 216 + 217 + Ok x -> 218 + handleError model "Invalid response from SignIn" 219 + 220 + Err err -> 221 + handleError model err 212 222 213 - Redirect -> 214 - (!) model [] 223 + Incoming SignIn (Err err) -> 224 + handleError model err 215 225 216 226 ------------------------------------ 217 227 -- Sign out 218 228 ------------------------------------ 219 - SignOut -> 229 + PerformSignOut -> 220 230 (!) 221 - { model | method = Nothing, signedIn = False } 222 - [ Task.attempt 223 - (always TopLevel.NoOp) 224 - (Authentication.Method.remove) 225 - , case model.method of 226 - Just method -> 227 - Task.attempt 228 - (always TopLevel.NoOp) 229 - (Authentication.Method.deconstruct method) 231 + { model | signedIn = False } 232 + [ do TopLevel.ShowLoadingScreen 233 + , issue SignOut 234 + ] 235 + 236 + ------------------------------------ 237 + -- Sign out / Events 238 + ------------------------------------ 239 + Incoming SignOut (Ok _) -> 240 + (!) model [ issue Deconstruct ] 241 + 242 + Incoming SignOut (Err err) -> 243 + handleError model err 244 + 245 + Incoming Deconstruct (Ok _) -> 246 + (!) model [ issue MethodUnset ] 247 + 248 + Incoming Deconstruct (Err err) -> 249 + handleError model err 250 + 251 + Incoming MethodUnset (Ok _) -> 252 + (!) { model | method = Nothing } [ do TopLevel.Reset ] 253 + 254 + Incoming MethodUnset (Err err) -> 255 + handleError model err 256 + 257 + ------------------------------------ 258 + -- Data storage 259 + ------------------------------------ 260 + Incoming StoreData _ -> 261 + (!) model [] 262 + 230 263 231 - Nothing -> 232 - Cmd.none 233 264 234 - -- Clear all data 235 - , do TopLevel.Reset 236 - ] 265 + -- 🔥 / Utilities 237 266 238 267 239 - after : Cmd TopLevel.Msg 240 - after = 268 + afterwards : Cmd TopLevel.Msg 269 + afterwards = 241 270 do TopLevel.HideLoadingScreen 271 + 272 + 273 + displayError : String -> Cmd TopLevel.Msg 274 + displayError error = 275 + error 276 + |> ErrorScreen 277 + |> Routing.Types.SetPage 278 + |> TopLevel.RoutingMsg 279 + |> do 280 + 281 + 282 + handleError : Model -> String -> ( Model, Cmd TopLevel.Msg ) 283 + handleError model error = 284 + (!) 285 + model 286 + [ afterwards 287 + , displayError error 288 + ] 289 + 290 + 291 + issue : OutgoingMsg -> Cmd TopLevel.Msg 292 + issue msg = 293 + issueWithData msg Encode.null 294 + 295 + 296 + issueWithData : OutgoingMsg -> Encode.Value -> Cmd TopLevel.Msg 297 + issueWithData msg data = 298 + Ports.authenticationEvent 299 + { tag = Transformers.outgoingMessageToString msg 300 + , data = data 301 + , error = Nothing 302 + } 303 + 304 + 305 + 306 + -- 🌱 307 + 308 + 309 + subscriptions : Model -> Sub Msg 310 + subscriptions _ = 311 + Sub.batch 312 + [ Ports.authenticationEventResult toMessage 313 + ] 314 + 315 + 316 + toMessage : OutsideEvent -> Msg 317 + toMessage event = 318 + Incoming 319 + (Transformers.stringToOutgoingMessage event.tag) 320 + (case event.error of 321 + Just err -> 322 + Err err 323 + 324 + Nothing -> 325 + Ok event.data 326 + )
+85
src/App/Authentication/Transformers.elm
··· 1 + module Authentication.Transformers exposing (..) 2 + 3 + import Authentication.Types exposing (..) 4 + import String.Extra 5 + 6 + 7 + -- Methods 8 + 9 + 10 + stringToMethod : String -> Method 11 + stringToMethod str = 12 + case str of 13 + "BLOCKSTACK" -> 14 + Blockstack 15 + 16 + "LOCAL" -> 17 + Local 18 + 19 + _ -> 20 + Debug.crash "Invalid authentication method" 21 + 22 + 23 + methodToString : Method -> String 24 + methodToString method = 25 + case method of 26 + Blockstack -> 27 + "BLOCKSTACK" 28 + 29 + Local -> 30 + "LOCAL" 31 + 32 + 33 + 34 + -- Outgoing messages 35 + 36 + 37 + stringToOutgoingMessage : String -> OutgoingMsg 38 + stringToOutgoingMessage str = 39 + case str of 40 + "METHOD_GET" -> 41 + MethodGet 42 + 43 + "METHOD_SET" -> 44 + MethodSet 45 + 46 + "METHOD_UNSET" -> 47 + MethodUnset 48 + 49 + "CONSTRUCT" -> 50 + Construct 51 + 52 + "DECONSTRUCT" -> 53 + Deconstruct 54 + 55 + "IS_SIGNED_IN" -> 56 + IsSignedIn 57 + 58 + "IS_SIGNING_IN" -> 59 + IsSigningIn 60 + 61 + "HANDLE_SIGN_IN_PROCESS" -> 62 + HandleSignInProcess 63 + 64 + "SIGN_IN" -> 65 + SignIn 66 + 67 + "SIGN_OUT" -> 68 + SignOut 69 + 70 + "GET_DATA" -> 71 + GetData 72 + 73 + "STORE_DATA" -> 74 + StoreData 75 + 76 + _ -> 77 + Debug.crash "Invalid OutgoingMsg" 78 + 79 + 80 + outgoingMessageToString : OutgoingMsg -> String 81 + outgoingMessageToString msg = 82 + msg 83 + |> toString 84 + |> String.Extra.underscored 85 + |> String.toUpper
+35 -24
src/App/Authentication/Types.elm
··· 1 1 module Authentication.Types exposing (..) 2 2 3 3 import Json.Encode 4 - import LocalStorage 5 4 6 5 7 6 -- Settings Types 8 7 9 - import Equalizer.Types as Equalizer 10 - import Queue.Types as Queue 11 - import Settings.Types as Settings 12 8 import Sources.Types as Sources 13 9 import Tracks.Types as Tracks 14 10 ··· 17 13 18 14 19 15 type Msg 20 - = DidGetData (Result String (Maybe String)) 21 - | DidGetMethod (Result LocalStorage.Error (Maybe Method)) 22 - | DidGetIsSignedIn Bool 23 - | DidGetIsSigningIn Bool 24 - | DidConstruct (Result () ()) 25 - | DidSignIn SignInConsequence 26 - | DidHandleSignInProcess SignInProcessConsequence 27 - -- 28 - | SignIn Method 29 - | SignOut 16 + = Incoming OutgoingMsg IncomingResult 17 + | PerformSignIn Method 18 + | PerformSignOut 30 19 31 20 32 21 ··· 40 29 41 30 42 31 32 + -- Talking to the outside world 33 + 34 + 35 + type OutgoingMsg 36 + = MethodGet 37 + | MethodSet 38 + | MethodUnset 39 + -- 40 + | Construct 41 + | Deconstruct 42 + | IsSignedIn 43 + | IsSigningIn 44 + | HandleSignInProcess 45 + | SignIn 46 + | SignOut 47 + | GetData 48 + | StoreData 49 + 50 + 51 + type alias OutgoingEvent = 52 + { tag : OutgoingMsg, data : Maybe Json.Encode.Value } 53 + 54 + 55 + type alias OutsideEvent = 56 + { tag : String, data : Json.Encode.Value, error : Maybe String } 57 + 58 + 59 + type alias IncomingResult = 60 + Result String Json.Encode.Value 61 + 62 + 63 + 43 64 -- Other 44 65 45 66 46 67 type Method 47 68 = Blockstack 48 69 | Local 49 - 50 - 51 - type SignInConsequence 52 - = None 53 - | Redirect 54 - 55 - 56 - type SignInProcessConsequence 57 - = KeepUrl 58 - | ModifyUrl 59 70 60 71 61 72 type alias UserData =
-78
src/App/Native/Authentication/Blockstack.js
··· 1 - const _icidasset$ongaku_ryoho$Native_Authentication_Blockstack = (() => { 2 - 3 - const KEY = "ongaku-ryoho.json"; 4 - 5 - const nativeBinding = _elm_lang$core$Native_Scheduler.nativeBinding; 6 - const succeed = _elm_lang$core$Native_Scheduler.succeed; 7 - const fail = _elm_lang$core$Native_Scheduler.fail; 8 - const Just = _elm_lang$core$Maybe$Just; 9 - const Nothing = _elm_lang$core$Maybe$Nothing; 10 - 11 - 12 - function native(fn) { 13 - return nativeBinding(callback => callback(succeed(fn()))); 14 - } 15 - 16 - 17 - let worker; 18 - 19 - 20 - return { 21 - 22 - construct: native(() => { 23 - worker = new Worker("/workers/authentication/blockstack.js"); 24 - }), 25 - 26 - deconstruct: native(() => { 27 - worker.terminate(); 28 - worker = null; 29 - }), 30 - 31 - // In & Out 32 - 33 - isSignedIn: native( 34 - blockstack.isUserSignedIn 35 - ), 36 - 37 - isSigningIn: native( 38 - blockstack.isSignInPending 39 - ), 40 - 41 - handleSignInProcess: nativeBinding(callback => { 42 - blockstack.handlePendingSignIn().then( 43 - user => callback(succeed({ ctor: "ModifyUrl" })), 44 - err => callback(fail(err)) 45 - ); 46 - }), 47 - 48 - signIn: native(() => { 49 - blockstack.redirectToSignIn(); 50 - return { ctor: "Redirect" }; 51 - }), 52 - 53 - signOut: native( 54 - blockstack.signUserOut 55 - ), 56 - 57 - 58 - // Data 59 - 60 - getData: nativeBinding(callback => { 61 - blockstack.getFile(KEY).then( 62 - data => callback(succeed(data ? Just(data) : Nothing)), 63 - err => callback(fail(err)) 64 - ); 65 - }), 66 - 67 - storeData(json) { 68 - return nativeBinding(callback => { 69 - blockstack.putFile(KEY, json).then( 70 - _ => callback(succeed()), 71 - err => callback(fail(err)) 72 - ); 73 - }); 74 - } 75 - 76 - }; 77 - 78 - })();
-126
src/App/Native/Authentication/Local.js
··· 1 - const _icidasset$ongaku_ryoho$Native_Authentication_Local = (() => { 2 - 3 - const ID = "authenticationMethod.LOCAL"; 4 - 5 - const nativeBinding = _elm_lang$core$Native_Scheduler.nativeBinding; 6 - const succeed = _elm_lang$core$Native_Scheduler.succeed; 7 - const fail = _elm_lang$core$Native_Scheduler.fail; 8 - const Just = _elm_lang$core$Maybe$Just; 9 - const Nothing = _elm_lang$core$Maybe$Nothing; 10 - 11 - 12 - // Utils 13 - 14 - function native(fn) { 15 - return nativeBinding(callback => callback(succeed(fn()))); 16 - } 17 - 18 - 19 - function doWork(reqs) { 20 - const timeoutId = setTimeout(_ => { 21 - reqs.callback(fail("Failed to reach web worker")); 22 - }, 60000); 23 - 24 - // Wait for response from worker, 25 - // have timeout as fallback. 26 - const patchedHandler = event => { 27 - worker.removeEventListener("message", patchedHandler); 28 - clearTimeout(timeoutId); 29 - reqs.handler(event); 30 - }; 31 - 32 - worker.addEventListener("message", patchedHandler); 33 - worker.postMessage({ action: reqs.action, data: reqs.data }); 34 - } 35 - 36 - 37 - let worker; 38 - 39 - 40 - return { 41 - 42 - construct: nativeBinding(callback => { 43 - worker = new Worker("/workers/authentication/local.js"); 44 - worker.onmessage = event => { 45 - worker.onmessage = null; 46 - 47 - switch (event.data.action) { 48 - case "CONSTRUCT_SUCCESS": return callback(succeed()); 49 - case "CONSTRUCT_FAILURE": return callback(fail()); 50 - } 51 - }; 52 - }), 53 - 54 - deconstruct: native(() => { 55 - worker.terminate(); 56 - worker = null; 57 - }), 58 - 59 - // In & Out 60 - 61 - isSignedIn: native( 62 - () => !!localStorage.getItem(ID) 63 - ), 64 - 65 - isSigningIn: native( 66 - () => false 67 - ), 68 - 69 - handleSignInProcess: native( 70 - () => ({ ctor: "KeepUrl" }) 71 - ), 72 - 73 - signIn: native(() => { 74 - localStorage.setItem(ID, "t"); 75 - return { ctor: "None" }; 76 - }), 77 - 78 - signOut: native(() => { 79 - localStorage.removeItem(ID) 80 - }), 81 - 82 - 83 - // GET DATA 84 - 85 - getData: nativeBinding(callback => { 86 - const handler = event => { 87 - switch (event.data.action) { 88 - case "GET_SUCCESS": return event.data.data 89 - ? callback(succeed( Just(event.data.data) )) 90 - : callback(succeed( Nothing )); 91 - 92 - case "GET_FAILURE": return callback(fail("Failed to get data")); 93 - default: return callback(fail("Unavailable")); 94 - } 95 - }; 96 - 97 - doWork({ 98 - action: "GET", 99 - data: null, 100 - callback: callback, 101 - handler: handler 102 - }); 103 - }), 104 - 105 - // STORE DATA 106 - 107 - storeData(json) { return nativeBinding(callback => { 108 - const handler = event => { 109 - switch (event.data.action) { 110 - case "SET_SUCCESS": return callback(succeed()); 111 - case "SET_FAILURE": return callback(fail("Failed to store data")); 112 - default: return callback(fail("Unavailable")); 113 - } 114 - }; 115 - 116 - doWork({ 117 - action: "SET", 118 - data: json, 119 - callback: callback, 120 - handler: handler 121 - }); 122 - })} 123 - 124 - }; 125 - 126 - })();
+1 -1
src/App/Settings/View.elm
··· 46 46 [ Icons.exit_to_app colorDerivatives.text 16 47 47 , label [] [ text "Sign out" ] 48 48 ] 49 - , AuthenticationMsg Authentication.SignOut 49 + , AuthenticationMsg Authentication.PerformSignOut 50 50 ) 51 51 ] 52 52
+10 -11
src/App/State.elm
··· 1 1 module State exposing (..) 2 2 3 - import Authentication.Method 4 - import Authentication.UserData 5 3 import Date 6 4 import Debounce 5 + import Json.Encode 7 6 import List.Extra as List 8 7 import Maybe.Extra as Maybe 9 8 import Navigation ··· 32 31 33 32 -- Children, Pt. 2 34 33 34 + import Authentication.Types 35 + import Authentication.UserData 35 36 import Playlists.Types 36 37 import Playlists.Utils 37 38 import Queue.Ports ··· 151 152 StoreUserData -> 152 153 (!) 153 154 model 154 - [ case model.authentication.method of 155 - Just method -> 156 - model 157 - |> Authentication.UserData.outwards 158 - |> Authentication.Method.storeData method 159 - |> Task.attempt DidStoreUserData 160 - 161 - Nothing -> 162 - Cmd.none 155 + [ Authentication.issueWithData 156 + Authentication.Types.StoreData 157 + (model 158 + |> Authentication.UserData.outwards 159 + |> Json.Encode.string 160 + ) 163 161 ] 164 162 165 163 DidStoreUserData (Ok _) -> ··· 393 391 , Ports.setIsTouchDevice SetIsTouchDevice 394 392 395 393 -- Children 394 + , Sub.map AuthenticationMsg <| Authentication.subscriptions model.authentication 396 395 , Sub.map ConsoleMsg <| Console.subscriptions model.console 397 396 , Sub.map EqualizerMsg <| Equalizer.subscriptions model.equalizer 398 397 , Sub.map QueueMsg <| Queue.subscriptions model.queue
+1 -1
src/App/View.elm
··· 254 254 a 255 255 [ cssClass AuthenticationButton 256 256 , authMethod 257 - |> Authentication.Types.SignIn 257 + |> Authentication.Types.PerformSignIn 258 258 |> AuthenticationMsg 259 259 |> onClick 260 260 ]
+8
src/Js/audio-engine.js
··· 1 + // 2 + // Audio engine 3 + // ♪(´ε` ) 4 + // 5 + // Creates audio elements and interacts with the Web Audio API. 6 + 7 + 8 + 1 9 // 2 10 // Audio context 3 11
+226
src/Js/authentication.js
··· 1 + // 2 + // Authentication 3 + // [≡] 〆(・⺫・‶) 4 + // 5 + // Different integrations for authentication: 6 + // 1. Local (indexedDB) 7 + // 2. Blockstack 8 + 9 + const AUTH_SYSTEM = {}; 10 + 11 + 12 + 13 + // 14 + // > Utilities 15 + 16 + function doWork(worker, requisites) { 17 + const timeoutId = setTimeout(_ => { 18 + requisites.reject("Failed to reach web worker"); 19 + }, 60000); 20 + 21 + // Wait for response from worker, 22 + // have timeout as fallback. 23 + const patchedHandler = event => { 24 + worker.removeEventListener("message", patchedHandler); 25 + clearTimeout(timeoutId); 26 + requisites.handler(event); 27 + }; 28 + 29 + worker.addEventListener("message", patchedHandler); 30 + worker.postMessage({ action: requisites.action, data: requisites.data }); 31 + } 32 + 33 + 34 + function promised(fn) { 35 + return () => new Promise(fn); 36 + } 37 + 38 + 39 + function resolved(fn) { 40 + return () => Promise.resolve(fn.call(this)); 41 + } 42 + 43 + 44 + 45 + // 46 + // > Method 47 + 48 + const METHOD_KEY = 49 + "authenticationMethod"; 50 + 51 + 52 + AUTH_SYSTEM.METHOD = 53 + { get: _ => localStorage.getItem(METHOD_KEY) 54 + , set: v => localStorage.setItem(METHOD_KEY, v) 55 + , unset: _ => localStorage.removeItem(METHOD_KEY) 56 + }; 57 + 58 + 59 + 60 + // 61 + // 1. Local 62 + 63 + (() => { 64 + 65 + let ID = "authenticationMethod.LOCAL"; 66 + let worker; 67 + 68 + 69 + AUTH_SYSTEM.LOCAL = { 70 + 71 + construct: promised((resolve, reject) => { 72 + worker = new Worker("/workers/authentication/local.js"); 73 + worker.onmessage = event => { 74 + worker.onmessage = null; 75 + 76 + switch (event.data.action) { 77 + case "CONSTRUCT_SUCCESS": return resolve(); 78 + case "CONSTRUCT_FAILURE": return reject(); 79 + } 80 + }; 81 + }), 82 + 83 + deconstruct: resolved(() => { 84 + worker.terminate(); 85 + worker = null; 86 + }), 87 + 88 + // In & Out 89 + 90 + isSignedIn: resolved( 91 + () => !!localStorage.getItem(ID) 92 + ), 93 + 94 + isSigningIn: resolved( 95 + () => false 96 + ), 97 + 98 + handleSignInProcess: resolved(() => { 99 + return "KeepUrl"; 100 + }), 101 + 102 + signIn: resolved(() => { 103 + localStorage.setItem(ID, "t"); 104 + return "None"; 105 + }), 106 + 107 + signOut: resolved(() => { 108 + localStorage.removeItem(ID); 109 + }), 110 + 111 + // Get data 112 + 113 + getData: promised((resolve, reject) => { 114 + const handler = event => { 115 + switch (event.data.action) { 116 + case "GET_SUCCESS": return event.data.data 117 + ? resolve( event.data.data ) 118 + : resolve( null ); 119 + 120 + case "GET_FAILURE": return reject("Failed to get data"); 121 + default: return reject("Unavailable"); 122 + } 123 + }; 124 + 125 + doWork(worker, { 126 + action: "GET", 127 + data: null, 128 + resolve: resolve, 129 + reject: reject, 130 + handler: handler 131 + }); 132 + }), 133 + 134 + // Store data 135 + 136 + storeData: json => new Promise((resolve, reject) => { 137 + const handler = event => { 138 + switch (event.data.action) { 139 + case "SET_SUCCESS": return resolve(); 140 + case "SET_FAILURE": return reject("Failed to store data"); 141 + default: return reject("Unavailable"); 142 + } 143 + }; 144 + 145 + doWork(worker, { 146 + action: "SET", 147 + data: json, 148 + resolve: resolve, 149 + reject: reject, 150 + handler: handler 151 + }); 152 + }) 153 + 154 + } 155 + 156 + })(); 157 + 158 + 159 + 160 + // 161 + // 2. Blockstack 162 + 163 + (() => { 164 + 165 + let KEY = "ongaku-ryoho.json"; 166 + let worker; 167 + 168 + 169 + AUTH_SYSTEM.BLOCKSTACK = { 170 + 171 + construct: resolved(() => { 172 + worker = new Worker("/workers/authentication/blockstack.js"); 173 + }), 174 + 175 + deconstruct: resolved(() => { 176 + worker.terminate(); 177 + worker = null; 178 + }), 179 + 180 + // In & Out 181 + 182 + isSignedIn: resolved( 183 + blockstack.isUserSignedIn 184 + ), 185 + 186 + isSigningIn: resolved( 187 + blockstack.isSignInPending 188 + ), 189 + 190 + handleSignInProcess: promised((resolve, reject) => { 191 + blockstack.handlePendingSignIn().then( 192 + user => resolve("ModifyUrl"), 193 + err => reject(err) 194 + ); 195 + }), 196 + 197 + signIn: resolved(() => { 198 + blockstack.redirectToSignIn(); 199 + return "Redirect"; 200 + }), 201 + 202 + signOut: resolved(() => { 203 + blockstack.signUserOut(); 204 + }), 205 + 206 + // Get data 207 + 208 + getData: promised((resolve, reject) => { 209 + blockstack.getFile(KEY).then( 210 + resolve, 211 + reject 212 + ); 213 + }), 214 + 215 + // Store data 216 + 217 + storeData: json => new Promise((resolve, reject) => { 218 + blockstack.putFile(KEY, json).then( 219 + _ => resolve(), 220 + err => reject(err) 221 + ); 222 + }) 223 + 224 + } 225 + 226 + })();
+44
src/Js/elm-loader.js
··· 1 1 // 2 + // Elm loader 2 3 // | (• ◡•)| (❍ᴥ❍ʋ) 4 + // 5 + // The bit where we launch the Elm app, 6 + // and connect the other bits to it. 3 7 4 8 let app, node; 5 9 ··· 7 11 node.innerHTML = ""; 8 12 9 13 app = Elm.App.embed(node); 14 + 15 + 16 + 17 + // 18 + // > Authentication 19 + 20 + app.ports.authenticationEvent.subscribe(event => { 21 + let funcName, method; 22 + let report = app.ports.authenticationEventResult.send; 23 + 24 + switch (event.tag) { 25 + 26 + case "METHOD_GET": 27 + case "METHOD_SET": 28 + case "METHOD_UNSET": 29 + // Call function on the METHOD object. 30 + // For example: METHOD_GET -> METHOD.get() 31 + funcName = camelcase(event.tag.replace(/^\w+_/, "")); 32 + 33 + report({ 34 + tag: event.tag, 35 + data: AUTH_SYSTEM.METHOD[funcName](event.data), 36 + error: null 37 + }); 38 + 39 + break; 40 + 41 + default: 42 + // Perform action on the active authentication method. 43 + // For example: CONSTRUCT -> LOCAL.construct() 44 + method = AUTH_SYSTEM.METHOD.get(); 45 + funcName = camelcase(event.tag); 46 + 47 + AUTH_SYSTEM[method][funcName]().then( 48 + data => report({ tag: event.tag, data: data, error: null }), 49 + err => report({ tag: event.tag, data: null, error: err.toString() }) 50 + ); 51 + 52 + } 53 + }); 10 54 11 55 12 56
+6
src/Js/processing.js
··· 1 + // 2 + // Processing 3 + // (◡ ‿ ◡ ✿) 4 + // 5 + // This code is responsible for extracting metadata out of files. 6 + 1 7 const tagSet = ["album", "artist", "disc", "genre", "nr", "picture", "title", "year"]; 2 8 3 9
+1
src/Static/Html/Proxy.html
··· 41 41 42 42 <script src="/application.js"></script> 43 43 <script src="/audio-engine.js"></script> 44 + <script src="/authentication.js"></script> 44 45 <script src="/processing.js"></script> 45 46 46 47 <script src="/elm-loader.js"></script>
+1
src/Vendor/package.js
··· 3 3 4 4 self._ = require("1-liners"); 5 5 self.blockstack = require("blockstack"); 6 + self.camelcase = require("camelcase"); 6 7 self.elasticlunr = require("elasticlunr"); 7 8 8 9 if (self.document) {