diff --git a/WEB/package-lock.json b/WEB/package-lock.json
index bd78330..13ac577 100644
--- a/WEB/package-lock.json
+++ b/WEB/package-lock.json
@@ -472,6 +472,11 @@
"tslib": "^1.9.0"
}
},
+ "@angular/fire": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/fire/-/fire-5.2.1.tgz",
+ "integrity": "sha512-pS4zWhLLANzMbYVIKNtebDQKhm9+KANUDvDV6DwKP24XHzkZdvazKe1HC6uXWlf7QmDxSPFleCSBkn0tnQQzdQ=="
+ },
"@angular/forms": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.2.0.tgz",
@@ -686,6 +691,258 @@
}
}
},
+ "@firebase/app": {
+ "version": "0.4.13",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.4.13.tgz",
+ "integrity": "sha512-LWiIKRoik1dFsY24k3pQ6NrQyWvSt+HzJKratUHfzqDBACdxcw7+9kwFMnS4MHGc/GGFVC42rHrI0PHeRe779w==",
+ "requires": {
+ "@firebase/app-types": "0.4.3",
+ "@firebase/logger": "0.1.21",
+ "@firebase/util": "0.2.24",
+ "dom-storage": "2.1.0",
+ "tslib": "1.10.0",
+ "xmlhttprequest": "1.8.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ }
+ }
+ },
+ "@firebase/app-types": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.4.3.tgz",
+ "integrity": "sha512-VU5c+ZjejvefLVH4cjiX3Hy1w9HYMv7TtZ1tF9ZmOqT4DSIU1a3VISWoo8///cGGffr5IirMO+Q/WZLI4p8VcA=="
+ },
+ "@firebase/auth": {
+ "version": "0.11.7",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.11.7.tgz",
+ "integrity": "sha512-qloLTfUPja0ivRvyC0FnEMif6bYPZb9DsJsV83KiBWaYMSkCeNHuA34p73JvjmgHrT571t+zFpJ3OrBH+va4ow==",
+ "requires": {
+ "@firebase/auth-types": "0.7.2"
+ }
+ },
+ "@firebase/auth-types": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.7.2.tgz",
+ "integrity": "sha512-xm3evp6671LoI+6M8Om3OhikabLf88Ivz1e7aR8uZjVBYptEYbF3seDIyHn/3wWdVYbp20WK4aWixKlRnHl+6Q=="
+ },
+ "@firebase/database": {
+ "version": "0.4.11",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.4.11.tgz",
+ "integrity": "sha512-g6VcEiw1HqBbV31p0j61CleLKZQ2XEOqpv1MSuiH9YYMsbHI7uUaebj3dxIdLSdLMoWNpGYmlXva/AWkirAV8Q==",
+ "requires": {
+ "@firebase/database-types": "0.4.2",
+ "@firebase/logger": "0.1.21",
+ "@firebase/util": "0.2.24",
+ "faye-websocket": "0.11.3",
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "faye-websocket": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
+ "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ }
+ }
+ },
+ "@firebase/database-types": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.4.2.tgz",
+ "integrity": "sha512-rBF/Sp4S4zzVg+a6h0iEiXR2GdNRrvx2BR6IcvGHnSPF7XVpj9UuUWtZMJyO+vWP3zlIGDvlNRJ4qF01Y6KxGg=="
+ },
+ "@firebase/firestore": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.4.8.tgz",
+ "integrity": "sha512-/Ult2LpbweinNnpqGrGiMw+EAaMEy6uA71DWN868oZoUmnn/+s/DCe2J0P+On2HATqvg5WggrQRa9I0in8fFag==",
+ "requires": {
+ "@firebase/firestore-types": "1.4.4",
+ "@firebase/logger": "0.1.21",
+ "@firebase/util": "0.2.24",
+ "@firebase/webchannel-wrapper": "0.2.23",
+ "@grpc/proto-loader": "^0.5.0",
+ "grpc": "1.22.2",
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ }
+ }
+ },
+ "@firebase/firestore-types": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-1.4.4.tgz",
+ "integrity": "sha512-kFpmzkUKfzrXkcMad+TQlMs55dWNY0q1UxGICW82EneX3Yg6HN3Nx36kYfqH+SLBFUN1ZTikN07alMp0MA9p9g=="
+ },
+ "@firebase/functions": {
+ "version": "0.4.14",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.14.tgz",
+ "integrity": "sha512-rWYWIp2NIRfNGREkSEhu9fD7WsqkUARnonn7+g+DOCxlf23AkwwDwp6q9cnSia7iJ9kmkiz4hyQVI0vB1QlV5A==",
+ "requires": {
+ "@firebase/functions-types": "0.3.8",
+ "@firebase/messaging-types": "0.3.2",
+ "isomorphic-fetch": "2.2.1",
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ }
+ }
+ },
+ "@firebase/functions-types": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.3.8.tgz",
+ "integrity": "sha512-9hajHxA4UWVCGFmoL8PBYHpamE3JTNjObieMmnvZw3cMRTP2EwipMpzZi+GPbMlA/9swF9yHCY/XFAEkwbvdgQ=="
+ },
+ "@firebase/installations": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.2.3.tgz",
+ "integrity": "sha512-HhHMn1xvyqBCvw8HmjZ5w856BQ0+xX4tKe/48k+dyKUzzSjwrFjILWTDV2GIHZcVyMHuSS3/bX9ehIBULB5yAA==",
+ "requires": {
+ "@firebase/installations-types": "0.1.2",
+ "@firebase/util": "0.2.24",
+ "idb": "3.0.2",
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ }
+ }
+ },
+ "@firebase/installations-types": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.1.2.tgz",
+ "integrity": "sha512-fQaWIW8hyX1XUN7+FCSPjvM1agFjGidVuF4Sxi7aFwfyh5t+4fD2VpM4wCQbWmodnx4fZLvsuQd9mkxxU+lGYQ=="
+ },
+ "@firebase/logger": {
+ "version": "0.1.21",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.21.tgz",
+ "integrity": "sha512-O4aIK1wkMpczqnDSwzDaEcQ8a5puVU4Bpt+16PfenicsBSrIR+gKq44crPM3nv/LURWtDpUVSYGoqhKPeodPAg=="
+ },
+ "@firebase/messaging": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.4.7.tgz",
+ "integrity": "sha512-Kzx64ELqOhEniyKawyCmDiQo8tX+wiF7Jsk5kp7moh7090dOPb8p8snkq770UFwUZjhouVrl8tOKzD3SInVIFA==",
+ "requires": {
+ "@firebase/messaging-types": "0.3.2",
+ "@firebase/util": "0.2.24",
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ }
+ }
+ },
+ "@firebase/messaging-types": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.3.2.tgz",
+ "integrity": "sha512-2qa2qNKqpalmtwaUV3+wQqfCm5myP/dViIBv+pXF8HinemIfO1IPQtr9pCNfsSYyus78qEhtfldnPWXxUH5v0w=="
+ },
+ "@firebase/performance": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.2.14.tgz",
+ "integrity": "sha512-WNhJkVEq9q6OazUldzeRcESmGl0W2kw82CfUII/uPATdMvF5wXvda60BN0zwquRVSdLTt7qVRQA/8wLQYnX/Kw==",
+ "requires": {
+ "@firebase/installations": "0.2.3",
+ "@firebase/logger": "0.1.21",
+ "@firebase/performance-types": "0.0.3",
+ "@firebase/util": "0.2.24",
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ }
+ }
+ },
+ "@firebase/performance-types": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.3.tgz",
+ "integrity": "sha512-RuC63nYJPJU65AsrNMc3fTRcRgHiyNcQLh9ufeKUT1mEsFgpxr167gMb+tpzNU4jsbvM6+c6nQAFdHpqcGkRlQ=="
+ },
+ "@firebase/polyfill": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.18.tgz",
+ "integrity": "sha512-Erp0vuFYMS8BlQzuAWR6zf10rxDT4GHRGJypxoW7arU4J61KIb6CPmrO9tVtf/rVEZuUXsDO65etDEFA8elCYA==",
+ "requires": {
+ "core-js": "3.1.4",
+ "promise-polyfill": "8.1.3",
+ "whatwg-fetch": "2.0.4"
+ },
+ "dependencies": {
+ "whatwg-fetch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
+ "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
+ }
+ }
+ },
+ "@firebase/storage": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.8.tgz",
+ "integrity": "sha512-u/JHEkoIPKkRigHhcHcmHq6Ymu27Iyei6SqDFPm17vfC85jDetdg6aO9K+UxbtdDICa60P86UguqDHTMLVwKIg==",
+ "requires": {
+ "@firebase/storage-types": "0.3.3",
+ "@firebase/util": "0.2.24",
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ }
+ }
+ },
+ "@firebase/storage-types": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.3.3.tgz",
+ "integrity": "sha512-fUp4kpbxwDiWs/aIBJqBvXgFHZvgoND2JA0gJYSEsXtWtVwfgzY/710plErgZDeQKopX5eOR1sHskZkQUy0U6w=="
+ },
+ "@firebase/util": {
+ "version": "0.2.24",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.24.tgz",
+ "integrity": "sha512-XFBNxfkMajl2zSUdcCQ3H32IN9JSM7Dacv8RK72DKoFV8Zn8dx4iZvtx8RB/VTFpXfcl435A0RzXqkLfSSEK/A==",
+ "requires": {
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ }
+ }
+ },
+ "@firebase/webchannel-wrapper": {
+ "version": "0.2.23",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.2.23.tgz",
+ "integrity": "sha512-BJqOF51sPQjmRoX+WFMbZ5mhuy53JrFN0t1KY+HffcvDRb+82+vkFatKnwG3wTCKV183vJW5tGQIytb4T8pUBg=="
+ },
"@fortawesome/angular-fontawesome": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.4.0.tgz",
@@ -715,6 +972,15 @@
"@fortawesome/fontawesome-common-types": "^0.2.21"
}
},
+ "@grpc/proto-loader": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.1.tgz",
+ "integrity": "sha512-3y0FhacYAwWvyXshH18eDkUI40wT/uGio7MAegzY8lO5+wVsc19+1A7T0pPptae4kl7bdITL+0cHpnAPmryBjQ==",
+ "requires": {
+ "lodash.camelcase": "^4.3.0",
+ "protobufjs": "^6.8.6"
+ }
+ },
"@ngtools/webpack": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.2.0.tgz",
@@ -739,6 +1005,60 @@
}
}
},
+ "@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78="
+ },
+ "@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
+ },
+ "@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
+ },
+ "@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A="
+ },
+ "@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E="
+ },
+ "@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik="
+ },
+ "@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0="
+ },
+ "@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q="
+ },
+ "@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
+ },
"@schematics/angular": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.2.0.tgz",
@@ -814,6 +1134,11 @@
"@types/jasmine": "*"
}
},
+ "@types/long": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz",
+ "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q=="
+ },
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -1169,8 +1494,7 @@
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
"version": "3.2.1",
@@ -1300,6 +1624,15 @@
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
"dev": true
},
+ "ascli": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz",
+ "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=",
+ "requires": {
+ "colour": "~0.7.1",
+ "optjs": "~3.2.2"
+ }
+ },
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -1580,8 +1913,7 @@
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"base": {
"version": "0.11.2",
@@ -1769,7 +2101,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -1970,6 +2301,21 @@
"integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
"dev": true
},
+ "bytebuffer": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz",
+ "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=",
+ "requires": {
+ "long": "~3"
+ },
+ "dependencies": {
+ "long": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
+ "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s="
+ }
+ }
+ },
"bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
@@ -2366,8 +2712,7 @@
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
- "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"codelyzer": {
"version": "5.1.0",
@@ -2431,6 +2776,11 @@
"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
"dev": true
},
+ "colour": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz",
+ "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g="
+ },
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -2503,8 +2853,7 @@
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"concat-stream": {
"version": "1.6.2",
@@ -2816,8 +3165,7 @@
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
- "dev": true
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"decode-uri-component": {
"version": "0.2.0",
@@ -3090,6 +3438,11 @@
"void-elements": "^2.0.0"
}
},
+ "dom-storage": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz",
+ "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q=="
+ },
"domain-browser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
@@ -3167,7 +3520,6 @@
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
"integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
- "dev": true,
"requires": {
"iconv-lite": "~0.4.13"
}
@@ -3777,6 +4129,25 @@
"locate-path": "^3.0.0"
}
},
+ "firebase": {
+ "version": "6.3.4",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-6.3.4.tgz",
+ "integrity": "sha512-UvLCXApdrhYZkGl1N/4dPPFVa3zFd+K963guaP9ckQhagch66Hv1xLwL8urmlBAGk9UZECMAk8f7YcLD217HkA==",
+ "requires": {
+ "@firebase/app": "0.4.13",
+ "@firebase/app-types": "0.4.3",
+ "@firebase/auth": "0.11.7",
+ "@firebase/database": "0.4.11",
+ "@firebase/firestore": "1.4.8",
+ "@firebase/functions": "0.4.14",
+ "@firebase/installations": "0.2.3",
+ "@firebase/messaging": "0.4.7",
+ "@firebase/performance": "0.2.14",
+ "@firebase/polyfill": "0.3.18",
+ "@firebase/storage": "0.3.8",
+ "@firebase/util": "0.2.24"
+ }
+ },
"flatted": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
@@ -3917,8 +4288,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "1.2.9",
@@ -4514,7 +4884,6 @@
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
- "dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -4579,6 +4948,493 @@
"integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
"dev": true
},
+ "grpc": {
+ "version": "1.22.2",
+ "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.22.2.tgz",
+ "integrity": "sha512-gaK59oAA5/mlOIn+hQO5JROPoAzsaGRpEMcrAayW5WGETS8QScpBoQ+XBxEWAAF0kbeGIELuGRCVEObKS1SLmw==",
+ "requires": {
+ "lodash.camelcase": "^4.3.0",
+ "lodash.clone": "^4.5.0",
+ "nan": "^2.13.2",
+ "node-pre-gyp": "^0.13.0",
+ "protobufjs": "^5.0.3"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "bundled": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "bundled": true
+ },
+ "cliui": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wrap-ansi": "^2.0.0"
+ }
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true
+ },
+ "fs-minipass": {
+ "version": "1.2.6",
+ "bundled": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true
+ },
+ "iconv-lite": {
+ "version": "0.4.23",
+ "bundled": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+ "requires": {
+ "invert-kv": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true
+ },
+ "minipass": {
+ "version": "2.3.5",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "bundled": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "requires": {
+ "minimist": "0.0.8"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true
+ }
+ }
+ },
+ "needle": {
+ "version": "2.4.0",
+ "bundled": true,
+ "requires": {
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "bundled": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "bundled": true
+ }
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.13.0",
+ "bundled": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "bundled": true
+ },
+ "npm-packlist": {
+ "version": "1.4.1",
+ "bundled": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "os-locale": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+ "requires": {
+ "lcid": "^1.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "bundled": true
+ },
+ "protobufjs": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz",
+ "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==",
+ "requires": {
+ "ascli": "~1",
+ "bytebuffer": "~5",
+ "glob": "^7.0.5",
+ "yargs": "^3.10.0"
+ }
+ },
+ "rc": {
+ "version": "1.2.8",
+ "bundled": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "bundled": true,
+ "requires": {
+ "glob": "^7.1.3"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.4",
+ "bundled": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true
+ },
+ "semver": {
+ "version": "5.7.0",
+ "bundled": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "signal-exit": {
+ "version": "3.0.1",
+ "bundled": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true
+ },
+ "tar": {
+ "version": "4.4.10",
+ "bundled": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.5",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "bundled": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "bundled": true
+ },
+ "yargs": {
+ "version": "3.32.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
+ "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=",
+ "requires": {
+ "camelcase": "^2.0.1",
+ "cliui": "^3.0.3",
+ "decamelize": "^1.1.1",
+ "os-locale": "^1.4.0",
+ "string-width": "^1.0.1",
+ "window-size": "^0.1.4",
+ "y18n": "^3.2.0"
+ }
+ }
+ }
+ },
"handle-thing": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
@@ -4789,8 +5645,7 @@
"http-parser-js": {
"version": "0.4.10",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
- "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=",
- "dev": true
+ "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q="
},
"http-proxy": {
"version": "1.17.0",
@@ -4893,11 +5748,15 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
+ "idb": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz",
+ "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw=="
+ },
"ieee754": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
@@ -4998,7 +5857,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@@ -5007,8 +5865,7 @@
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
"version": "1.3.5",
@@ -5255,7 +6112,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -5346,8 +6202,7 @@
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
- "dev": true
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"is-symbol": {
"version": "1.0.2",
@@ -5403,6 +6258,15 @@
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
"dev": true
},
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+ "requires": {
+ "node-fetch": "^1.0.1",
+ "whatwg-fetch": ">=0.10.0"
+ }
+ },
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -5996,6 +6860,16 @@
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
+ "lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
+ },
+ "lodash.clone": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz",
+ "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y="
+ },
"lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
@@ -6044,6 +6918,11 @@
"integrity": "sha512-LoEDv5pgpvWgPF4kNYuIp0qqSJVWak/dML0RY74xlzMZiT9w77teNAwKYKWBTYjlokMirg+o3jBwp+vlLrcfAA==",
"dev": true
},
+ "long": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
+ "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
+ },
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -6311,7 +7190,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -6460,9 +7338,7 @@
"nan": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
- "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
- "dev": true,
- "optional": true
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
},
"nanomatch": {
"version": "1.2.13",
@@ -6506,6 +7382,15 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
+ "node-fetch": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
+ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+ "requires": {
+ "encoding": "^0.1.11",
+ "is-stream": "^1.0.1"
+ }
+ },
"node-fetch-npm": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz",
@@ -6681,8 +7566,7 @@
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
- "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"oauth-sign": {
"version": "0.9.0",
@@ -6800,7 +7684,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
"requires": {
"wrappy": "1"
}
@@ -6858,6 +7741,11 @@
}
}
},
+ "optjs": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz",
+ "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4="
+ },
"original": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
@@ -7137,8 +8025,7 @@
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
- "dev": true
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-is-inside": {
"version": "1.0.2",
@@ -7371,6 +8258,11 @@
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
"dev": true
},
+ "promise-polyfill": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz",
+ "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g=="
+ },
"promise-retry": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz",
@@ -7389,6 +8281,33 @@
}
}
},
+ "protobufjs": {
+ "version": "6.8.8",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz",
+ "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/long": "^4.0.0",
+ "@types/node": "^10.1.0",
+ "long": "^4.0.0"
+ },
+ "dependencies": {
+ "@types/node": {
+ "version": "10.14.15",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.15.tgz",
+ "integrity": "sha512-CBR5avlLcu0YCILJiDIXeU2pTw7UK/NIxfC63m7d7CVamho1qDEzXKkOtEauQRPMy6MI8mLozth+JJkas7HY6g=="
+ }
+ }
+ },
"protoduck": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz",
@@ -8019,8 +8938,7 @@
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safe-regex": {
"version": "1.1.0",
@@ -8034,8 +8952,7 @@
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sass": {
"version": "1.22.7",
@@ -8968,7 +9885,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "dev": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -8988,7 +9904,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -9967,7 +10882,6 @@
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
"integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
- "dev": true,
"requires": {
"http-parser-js": ">=0.4.0 <0.4.11",
"safe-buffer": ">=5.1.0",
@@ -9977,8 +10891,12 @@
"websocket-extensions": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
- "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
- "dev": true
+ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg=="
+ },
+ "whatwg-fetch": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
+ "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
},
"when": {
"version": "3.6.4",
@@ -10001,6 +10919,11 @@
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
+ "window-size": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz",
+ "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY="
+ },
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
@@ -10029,7 +10952,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
- "dev": true,
"requires": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1"
@@ -10038,8 +10960,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "3.3.3",
@@ -10076,6 +10997,11 @@
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
"dev": true
},
+ "xmlhttprequest": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
+ "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw="
+ },
"xmlhttprequest-ssl": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
diff --git a/WEB/package.json b/WEB/package.json
index f91a3e9..e999491 100644
--- a/WEB/package.json
+++ b/WEB/package.json
@@ -17,6 +17,7 @@
"@angular/common": "~8.2.0",
"@angular/compiler": "~8.2.0",
"@angular/core": "~8.2.0",
+ "@angular/fire": "^5.2.1",
"@angular/forms": "~8.2.0",
"@angular/http": "~7.2.15",
"@angular/material": "^8.1.2",
@@ -28,6 +29,7 @@
"@fortawesome/free-solid-svg-icons": "^5.10.1",
"angular2-uuid": "^1.1.1",
"core-js": "^3.1.4",
+ "firebase": "^6.3.4",
"ng2-file-upload": "^1.3.0",
"odata-v4-ng": "^1.2.1",
"rxjs": "^6.5.2",
diff --git a/WEB/src/app/account/account-routing.module.ts b/WEB/src/app/account/account-routing.module.ts
new file mode 100644
index 0000000..c21a21d
--- /dev/null
+++ b/WEB/src/app/account/account-routing.module.ts
@@ -0,0 +1,17 @@
+import {NgModule} from '@angular/core';
+import {RouterModule, Routes} from '@angular/router';
+
+const routes: Routes = [
+ {
+ path: 'login',
+ loadChildren: () => import('./modules/login/login.module').then(_ => _.LoginModule)
+ }
+ ]
+;
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class AccountRoutingModule {
+}
diff --git a/WEB/src/app/account/account.module.ts b/WEB/src/app/account/account.module.ts
new file mode 100644
index 0000000..97b7bf8
--- /dev/null
+++ b/WEB/src/app/account/account.module.ts
@@ -0,0 +1,14 @@
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+
+import {AccountRoutingModule} from './account-routing.module';
+
+
+@NgModule({
+ imports: [
+ CommonModule,
+ AccountRoutingModule,
+ ]
+})
+export class AccountModule {
+}
diff --git a/WEB/src/app/account/modules/login/components/login/login.component.html b/WEB/src/app/account/modules/login/components/login/login.component.html
new file mode 100644
index 0000000..731a3a1
--- /dev/null
+++ b/WEB/src/app/account/modules/login/components/login/login.component.html
@@ -0,0 +1,21 @@
+
+
+ Login
+
+
+
+
+
+
+
+
+
+
diff --git a/WEB/src/app/account/modules/login/components/login/login.component.less b/WEB/src/app/account/modules/login/components/login/login.component.less
new file mode 100644
index 0000000..a5c2526
--- /dev/null
+++ b/WEB/src/app/account/modules/login/components/login/login.component.less
@@ -0,0 +1,5 @@
+form {
+ display: flex;
+ flex-direction: column;
+ padding: 20px 0;
+}
diff --git a/WEB/src/app/account/modules/login/components/login/login.component.spec.ts b/WEB/src/app/account/modules/login/components/login/login.component.spec.ts
new file mode 100644
index 0000000..cdf157d
--- /dev/null
+++ b/WEB/src/app/account/modules/login/components/login/login.component.spec.ts
@@ -0,0 +1,25 @@
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {LoginComponent} from './login.component';
+
+describe('LoginComponent', () => {
+ let component: LoginComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [LoginComponent]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(LoginComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/WEB/src/app/account/modules/login/components/login/login.component.ts b/WEB/src/app/account/modules/login/components/login/login.component.ts
new file mode 100644
index 0000000..e64d57d
--- /dev/null
+++ b/WEB/src/app/account/modules/login/components/login/login.component.ts
@@ -0,0 +1,41 @@
+import {Component, OnInit} from '@angular/core';
+import {AuthService} from '../../../../../services/auth.service';
+import {FormControl} from '@angular/forms';
+import {ActivatedRoute, Router} from '@angular/router';
+
+@Component({
+ selector: 'app-login',
+ templateUrl: './login.component.html',
+ styleUrls: ['./login.component.less']
+})
+export class LoginComponent implements OnInit {
+ public user = new FormControl();
+ public pass = new FormControl();
+ public loginError = false;
+
+ private redirect: string = null;
+
+ constructor(
+ private authService: AuthService,
+ private router: Router,
+ activatedRoute: ActivatedRoute
+ ) {
+ activatedRoute.queryParams.subscribe(_ => this.redirect = _.redirect);
+ }
+
+ ngOnInit() {
+ this.loginError = false;
+ }
+
+ public onLogin(): void {
+ this.authService.login$(this.user.value, this.pass.value).subscribe(_ => {
+ if (_ === null) {
+ this.loginError = true;
+ } else {
+ if (this.redirect) {
+ this.router.navigateByUrl('/' + this.redirect);
+ }
+ }
+ });
+ }
+}
diff --git a/WEB/src/app/account/modules/login/login-routing.module.ts b/WEB/src/app/account/modules/login/login-routing.module.ts
new file mode 100644
index 0000000..99c4042
--- /dev/null
+++ b/WEB/src/app/account/modules/login/login-routing.module.ts
@@ -0,0 +1,19 @@
+import {NgModule} from '@angular/core';
+import {RouterModule, Routes} from '@angular/router';
+import {LoginComponent} from './components/login/login.component';
+
+
+const routes: Routes = [
+ {
+ path: '',
+ component: LoginComponent,
+ pathMatch: 'full'
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class LoginRoutingModule {
+}
diff --git a/WEB/src/app/account/modules/login/login.module.ts b/WEB/src/app/account/modules/login/login.module.ts
new file mode 100644
index 0000000..8689770
--- /dev/null
+++ b/WEB/src/app/account/modules/login/login.module.ts
@@ -0,0 +1,24 @@
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+
+import {LoginRoutingModule} from './login-routing.module';
+import {LoginComponent} from './components/login/login.component';
+import {MatButtonModule, MatCardModule, MatInputModule} from '@angular/material';
+import {FormsModule, ReactiveFormsModule} from '@angular/forms';
+
+
+@NgModule({
+ declarations: [LoginComponent],
+ imports: [
+ CommonModule,
+ LoginRoutingModule,
+ FormsModule,
+ ReactiveFormsModule,
+
+ MatCardModule,
+ MatInputModule,
+ MatButtonModule
+ ]
+})
+export class LoginModule {
+}
diff --git a/WEB/src/app/app-routing.module.ts b/WEB/src/app/app-routing.module.ts
index 334302e..6bee292 100644
--- a/WEB/src/app/app-routing.module.ts
+++ b/WEB/src/app/app-routing.module.ts
@@ -1,5 +1,6 @@
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
+import {AuthGuard} from './guards/auth.guard';
const routes: Routes = [
@@ -10,7 +11,12 @@ const routes: Routes = [
},
{
path: 'songs',
- loadChildren: () => import('./songs/songs.module').then(_ => _.SongsModule)
+ loadChildren: () => import('./songs/songs.module').then(_ => _.SongsModule),
+ canActivate: [AuthGuard],
+ },
+ {
+ path: 'account',
+ loadChildren: () => import('./account/account.module').then(_ => _.AccountModule)
}
];
diff --git a/WEB/src/app/app.module.ts b/WEB/src/app/app.module.ts
index 94a8bd3..d95142b 100644
--- a/WEB/src/app/app.module.ts
+++ b/WEB/src/app/app.module.ts
@@ -19,6 +19,11 @@ import {MatSelectModule} from '@angular/material/select';
import {MatTooltipModule} from '@angular/material/tooltip';
import {MatProgressBarModule} from '@angular/material/progress-bar';
import {FileUploadModule} from 'ng2-file-upload';
+import {AngularFireModule} from '@angular/fire';
+import {AngularFireAuthModule} from '@angular/fire/auth';
+import {AngularFirestoreModule} from '@angular/fire/firestore';
+import {environment} from '../environments/environment';
+import {AngularFireDatabaseModule} from '@angular/fire/database';
@NgModule({
declarations: [
@@ -45,6 +50,11 @@ import {FileUploadModule} from 'ng2-file-upload';
FontAwesomeModule,
FileUploadModule,
AppRoutingModule,
+
+ AngularFireModule.initializeApp(environment.firebase),
+ AngularFirestoreModule, // imports firebase/firestore, only needed for database features
+ AngularFireAuthModule, // imports firebase/auth, only needed for auth features
+ AngularFireDatabaseModule,
],
providers: [],
bootstrap: [AppComponent]
diff --git a/WEB/src/app/guards/auth.guard.spec.ts b/WEB/src/app/guards/auth.guard.spec.ts
new file mode 100644
index 0000000..66586d9
--- /dev/null
+++ b/WEB/src/app/guards/auth.guard.spec.ts
@@ -0,0 +1,15 @@
+import {inject, TestBed} from '@angular/core/testing';
+
+import {AuthGuard} from './auth.guard';
+
+describe('AuthGuard', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [AuthGuard]
+ });
+ });
+
+ it('should ...', inject([AuthGuard], (guard: AuthGuard) => {
+ expect(guard).toBeTruthy();
+ }));
+});
diff --git a/WEB/src/app/guards/auth.guard.ts b/WEB/src/app/guards/auth.guard.ts
new file mode 100644
index 0000000..11ac400
--- /dev/null
+++ b/WEB/src/app/guards/auth.guard.ts
@@ -0,0 +1,27 @@
+import {Injectable} from '@angular/core';
+import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router';
+import {AuthService} from '../services/auth.service';
+import {Observable} from 'rxjs';
+import {map} from 'rxjs/operators';
+import {Role} from '../services/roles.model';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthGuard implements CanActivate {
+
+ constructor(private authService: AuthService,
+ private router: Router
+ ) {
+ }
+
+ canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable {
+ return this.authService.userMay$(Role.reader).pipe(
+ map(_ => {
+ return _
+ ? true
+ : this.router.createUrlTree(['/account/login'], {queryParams: {redirect: route.url}});
+ })
+ );
+ }
+}
diff --git a/WEB/src/app/services/access-right.service.spec.ts b/WEB/src/app/services/access-right.service.spec.ts
new file mode 100644
index 0000000..934a013
--- /dev/null
+++ b/WEB/src/app/services/access-right.service.spec.ts
@@ -0,0 +1,41 @@
+import {async, TestBed} from '@angular/core/testing';
+
+import {AccessRightService} from './access-right.service';
+import {AngularFirestore} from '@angular/fire/firestore';
+import {of} from 'rxjs';
+import {Role} from './roles.model';
+
+describe('AccessRightService', () => {
+ const mockAngularFirestore = {
+ collection: () => ({
+ doc: () => ({
+ valueChanges: () => of({
+ role: 'reader'
+ })
+ })
+ })
+ };
+
+ beforeEach(() => TestBed.configureTestingModule({
+ providers: [
+ {provide: AngularFirestore, useValue: mockAngularFirestore}
+ ]
+ }));
+
+ it('should be created', () => {
+ const service: AccessRightService = TestBed.get(AccessRightService);
+ expect(service).toBeTruthy();
+ });
+
+ it('should get user', async(() => {
+ const service: AccessRightService = TestBed.get(AccessRightService);
+ service.getUserInfo('userid').subscribe(_ => {
+ expect(_).toEqual({
+ user: 'userid',
+ role: Role.reader
+ });
+ });
+ }));
+
+
+});
diff --git a/WEB/src/app/services/access-right.service.ts b/WEB/src/app/services/access-right.service.ts
new file mode 100644
index 0000000..1d47d0d
--- /dev/null
+++ b/WEB/src/app/services/access-right.service.ts
@@ -0,0 +1,43 @@
+import {Injectable} from '@angular/core';
+import {AngularFirestore} from '@angular/fire/firestore';
+import {map} from 'rxjs/operators';
+import {User, UserDB} from './user.model';
+import {Observable} from 'rxjs';
+import {Role} from './roles.model';
+import {RoleDefinitions} from './role.definition';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AccessRightService {
+
+ constructor(
+ private angularFirestore: AngularFirestore
+ ) {
+ }
+
+ public getUserInfo(userId: string): Observable {
+ if (userId === null) {
+ return null;
+ }
+
+ const user$ = this.angularFirestore
+ .collection('/user')
+ .doc(userId)
+ .valueChanges()
+ .pipe
+ (map(user => ({
+ user: userId,
+ role: user.role
+ })));
+
+ return user$;
+ }
+
+ public userMay(role: Role, requestedRole: Role): boolean {
+ const allowedRoles = RoleDefinitions.filter(_ => _.role === requestedRole)[0].when;
+ const isAllowed = allowedRoles.indexOf(role) !== -1;
+
+ return isAllowed;
+ }
+}
diff --git a/WEB/src/app/services/auth.service.spec.ts b/WEB/src/app/services/auth.service.spec.ts
new file mode 100644
index 0000000..e5cb5fc
--- /dev/null
+++ b/WEB/src/app/services/auth.service.spec.ts
@@ -0,0 +1,47 @@
+import {fakeAsync, TestBed, tick} from '@angular/core/testing';
+
+import {AuthService} from './auth.service';
+import {of} from 'rxjs';
+import {Role} from './roles.model';
+import {AccessRightService} from './access-right.service';
+import {AngularFireAuth} from '@angular/fire/auth';
+
+describe('AuthService', () => {
+ const mockAccessRightService = {
+ getUserInfo: () => of({
+ user: 'userid',
+ role: Role.reader
+ })
+ };
+ const mockAngularFireAuth = {
+ auth: {
+ signInWithEmailAndPassword: Promise.resolve({user: {uid: 'userid'}})
+ }
+ };
+ beforeEach(() => TestBed.configureTestingModule({
+ providers: [
+ {provide: AccessRightService, useValue: mockAccessRightService},
+ {provide: AngularFireAuth, useValue: mockAngularFireAuth},
+ ]
+ }));
+
+ it('should be created', () => {
+ const service: AuthService = TestBed.get(AuthService);
+ expect(service).toBeTruthy();
+ });
+
+ it('should be created', fakeAsync(() => {
+ const service: AuthService = TestBed.get(AuthService);
+ const authSpy = spyOn(TestBed.get(AngularFireAuth).auth, 'signInWithEmailAndPassword');
+ const accessSpy = spyOn(TestBed.get(AccessRightService), 'getUserInfo');
+ service.login$('user', 'pass');
+
+ expect(authSpy).toHaveBeenCalledWith('user', 'pass');
+ tick();
+ expect(accessSpy).toHaveBeenCalledWith('userid');
+ tick();
+ expect(service.user.user).toBe('userid');
+ expect(service.user.user).toBe(Role.reader);
+
+ }));
+});
diff --git a/WEB/src/app/services/auth.service.ts b/WEB/src/app/services/auth.service.ts
new file mode 100644
index 0000000..35cf93d
--- /dev/null
+++ b/WEB/src/app/services/auth.service.ts
@@ -0,0 +1,64 @@
+import {Injectable} from '@angular/core';
+import {AngularFireAuth} from '@angular/fire/auth';
+import {from, Observable, of, OperatorFunction} from 'rxjs';
+import {AccessRightService} from './access-right.service';
+import {catchError, map, switchMap, tap} from 'rxjs/operators';
+import {User} from './user.model';
+import {Role} from './roles.model';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthService {
+ private _user: User = null;
+
+ constructor(
+ private angularFireAuth: AngularFireAuth,
+ private accessRightService: AccessRightService
+ ) {
+ angularFireAuth.authState.subscribe(_ => console.log(_));
+ }
+
+ public login$(user: string, pass: string): Observable {
+ const authPromise = this.angularFireAuth.auth.signInWithEmailAndPassword(user, pass);
+ const auth$ = from(authPromise).pipe(
+ map(_ => _.user.uid),
+ this.processLogin()
+ );
+
+ return auth$;
+ }
+
+ public getUser$(): Observable {
+ if (this._user) {
+ return of(this._user);
+ }
+
+ return this.angularFireAuth.authState.pipe(
+ map(_ => _ ? _.uid : null),
+ this.processLogin()
+ );
+ }
+
+ public userMay$(requestedRole: Role): Observable {
+ const allowed$ = this.getUser$().pipe(
+ map(_ => _ ? this.accessRightService.userMay(_.role, requestedRole) : false)
+ );
+
+ return allowed$;
+ }
+
+ private processLogin(): OperatorFunction {
+ const self = this;
+ return function (source$: Observable): Observable {
+ return source$.pipe(
+ switchMap(_ => self.accessRightService.getUserInfo(_)),
+ tap((_ => self._user = _)),
+ catchError(_ => {
+ self._user = null;
+ return of(null);
+ })
+ );
+ };
+ }
+}
diff --git a/WEB/src/app/services/role.definition.ts b/WEB/src/app/services/role.definition.ts
new file mode 100644
index 0000000..79e661f
--- /dev/null
+++ b/WEB/src/app/services/role.definition.ts
@@ -0,0 +1,7 @@
+import {Role} from './roles.model';
+
+export const RoleDefinitions = [
+ {role: Role.reader, when: [Role.admin, Role.writer, Role.reader]},
+ {role: Role.writer, when: [Role.admin, Role.writer]},
+ {role: Role.admin, when: [Role.admin]},
+];
diff --git a/WEB/src/app/services/roles.model.ts b/WEB/src/app/services/roles.model.ts
new file mode 100644
index 0000000..4070146
--- /dev/null
+++ b/WEB/src/app/services/roles.model.ts
@@ -0,0 +1,5 @@
+export enum Role {
+ admin = 'admin',
+ reader = 'reader',
+ writer = 'writer'
+}
diff --git a/WEB/src/app/services/user.model.ts b/WEB/src/app/services/user.model.ts
new file mode 100644
index 0000000..65b4d2a
--- /dev/null
+++ b/WEB/src/app/services/user.model.ts
@@ -0,0 +1,10 @@
+import {Role} from './roles.model';
+
+export interface User {
+ user: string;
+ role: Role;
+}
+
+export interface UserDB {
+ role: Role;
+}
diff --git a/WEB/src/app/songs/components/songs/table/table.component.less b/WEB/src/app/songs/components/songs/table/table.component.less
index 5b92298..1764daf 100644
--- a/WEB/src/app/songs/components/songs/table/table.component.less
+++ b/WEB/src/app/songs/components/songs/table/table.component.less
@@ -1,24 +1,4 @@
-table {
- border-radius: 8px;
- background: #fffe;
- tr.selected {
- background-color: #0002;
- }
-
- tr:hover {
- cursor: pointer;
- background-color: #0001;
-
- td {
- color: #ff9900;
- }
- }
-
- td.mat-cell {
- padding: 0 5px;
- }
-}
.table-container {
overflow: auto;
diff --git a/WEB/src/environments/environment.ts b/WEB/src/environments/environment.ts
index 1a0052d..03001be 100644
--- a/WEB/src/environments/environment.ts
+++ b/WEB/src/environments/environment.ts
@@ -4,7 +4,16 @@
export const environment = {
production: false,
- api: 'http://test.benjamin-ifland.de'
+ api: 'http://test.benjamin-ifland.de',
+ firebase: {
+ apiKey: 'AIzaSyBcIa6m8F7fT4gRLTx2zcBufUEE81gWVFg',
+ authDomain: 'worshipgenerator.firebaseapp.com',
+ databaseURL: 'https://worshipgenerator.firebaseio.com',
+ projectId: 'worshipgenerator',
+ storageBucket: 'worshipgenerator.appspot.com',
+ messagingSenderId: '317378238562',
+ appId: '1:317378238562:web:552ca27bc5e9086e'
+ }
};
/*
diff --git a/WEB/src/styles.less b/WEB/src/styles.less
index 114e428..32c6940 100644
--- a/WEB/src/styles.less
+++ b/WEB/src/styles.less
@@ -2,7 +2,14 @@
@import "~@angular/material/prebuilt-themes/indigo-pink.css";
html {
- background-image: url(https://images.unsplash.com/photo-1476136236990-838240be4859?ixlib=rb-1.2.1&auto=format&fit=crop&w=2167&q=80);
+ background: #2c3e50; /* fallback for old browsers */
+ background: -webkit-linear-gradient(to top, #2c3e50, #3498db); /* Chrome 10-25, Safari 5.1-6 */
+ background: linear-gradient(to top, #2c3e50, #3498db); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
+ height: 100vh;
+}
+
+.card-3 {
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
}
body {
@@ -14,53 +21,28 @@ body {
}
.page-container {
- padding: 10px;
- box-sizing: border-box;
+ .card-3;
+ margin: 10px;
overflow: hidden;
border-radius: 8px;
- .mat-table tbody {
+ table.mat-table thead,
+ table.mat-table tbody {
background: none;
}
- th.mat-header-cell:first-of-type {
- border-top-left-radius: 8px;
- }
-
- th.mat-header-cell:last-of-type {
- border-top-right-radius: 8px;
- }
-
- .mat-table thead {
- border-top-right-radius: 8px;
- border-top-left-radius: 8px;
- }
-
&.pinned {
padding: 0;
max-width: 300px;
- border-radius: 0;
-
- th.mat-header-cell:first-of-type {
- border-top-left-radius: 0;
- }
-
- th.mat-header-cell:last-of-type {
- border-top-right-radius: 0;
- }
-
- .mat-table thead {
- border-top-right-radius: 0;
- border-top-left-radius: 0;
- }
}
}
.mat-card {
+ .card-3;
width: 600px;
border-radius: 8px;
- background: #fffd;
+ background: #fffa;
margin: 10px;
box-sizing: border-box;
}
@@ -92,7 +74,7 @@ body {
padding: 0;
}
- table {
+ table.mat-table {
width: 100%;
background: none;
box-shadow: none;
@@ -105,4 +87,35 @@ body {
}
}
+ .mat-paginator {
+ background: #fffa;
+ }
+
+ table.mat-table {
+ background: #fffa;
+
+ tr.selected {
+ background-color: #0002;
+ }
+
+ tr:hover {
+ cursor: pointer;
+ background-color: #0001;
+
+ td {
+ color: #ff9900;
+ }
+ }
+
+ tr:focus {
+ outline: none;
+ }
+
+ td.mat-cell {
+ padding: 0 5px;
+ }
+
+
+ }
+
}
diff --git a/WEB/tslint.json b/WEB/tslint.json
index 6ddb6b2..64559a9 100644
--- a/WEB/tslint.json
+++ b/WEB/tslint.json
@@ -10,7 +10,6 @@
true,
"check-space"
],
- "curly": true,
"deprecation": {
"severity": "warn"
},