Merge pull request #105 from MycroftAI/test

Bug fixes, device delete
pull/107/head
Chris Veilleux 2019-04-08 16:44:00 -05:00 committed by GitHub
commit d9246d60ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 305 additions and 222 deletions

123
api/account/Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "3e2ce31477884f9983a6eb644183790f946eafc0b88a068507a8e42512c86d70"
"sha256": "051b0cfc68c8cfbc1a1a34aa80760a4bedaafa5bf366716a1d18918ce20f62a8"
},
"pipfile-spec": 6,
"requires": {
@ -18,10 +18,10 @@
"default": {
"certifi": {
"hashes": [
"sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7",
"sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"
"sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
"sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
],
"version": "==2018.11.29"
"version": "==2019.3.9"
},
"chardet": {
"hashes": [
@ -44,6 +44,13 @@
],
"version": "==1.2.5"
},
"facebook-sdk": {
"hashes": [
"sha256:2e987b3e0f466a6f4ee77b935eb023dba1384134f004a2af21f1cfff7fe0806e",
"sha256:cabcd2e69ea3d9f042919c99b353df7aa1e2be86d040121f6e9f5e63c1cf0f8d"
],
"version": "==3.1.0"
},
"flask": {
"hashes": [
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
@ -68,10 +75,10 @@
},
"jinja2": {
"hashes": [
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
"sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
"sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
],
"version": "==2.10"
"version": "==2.10.1"
},
"markupsafe": {
"hashes": [
@ -115,44 +122,42 @@
},
"psycopg2-binary": {
"hashes": [
"sha256:19a2d1f3567b30f6c2bb3baea23f74f69d51f0c06c2e2082d0d9c28b0733a4c2",
"sha256:2b69cf4b0fa2716fd977aa4e1fd39af6110eb47b2bb30b4e5a469d8fbecfc102",
"sha256:2e952fa17ba48cbc2dc063ddeec37d7dc4ea0ef7db0ac1eda8906365a8543f31",
"sha256:348b49dd737ff74cfb5e663e18cb069b44c64f77ec0523b5794efafbfa7df0b8",
"sha256:3d72a5fdc5f00ca85160915eb9a973cf9a0ab8148f6eda40708bf672c55ac1d1",
"sha256:4957452f7868f43f32c090dadb4188e9c74a4687323c87a882e943c2bd4780c3",
"sha256:5138cec2ee1e53a671e11cc519505eb08aaaaf390c508f25b09605763d48de4b",
"sha256:587098ca4fc46c95736459d171102336af12f0d415b3b865972a79c03f06259f",
"sha256:5b79368bcdb1da4a05f931b62760bea0955ee2c81531d8e84625df2defd3f709",
"sha256:5cf43807392247d9bc99737160da32d3fa619e0bfd85ba24d1c78db205f472a4",
"sha256:676d1a80b1eebc0cacae8dd09b2fde24213173bf65650d22b038c5ed4039f392",
"sha256:6b0211ecda389101a7d1d3df2eba0cf7ffbdd2480ca6f1d2257c7bd739e84110",
"sha256:79cde4660de6f0bb523c229763bd8ad9a93ac6760b72c369cf1213955c430934",
"sha256:7aba9786ac32c2a6d5fb446002ed936b47d5e1f10c466ef7e48f66eb9f9ebe3b",
"sha256:7c8159352244e11bdd422226aa17651110b600d175220c451a9acf795e7414e0",
"sha256:945f2eedf4fc6b2432697eb90bb98cc467de5147869e57405bfc31fa0b824741",
"sha256:96b4e902cde37a7fc6ab306b3ac089a3949e6ce3d824eeca5b19dc0bedb9f6e2",
"sha256:9a7bccb1212e63f309eb9fab47b6eaef796f59850f169a25695b248ca1bf681b",
"sha256:a3bfcac727538ec11af304b5eccadbac952d4cca1a551a29b8fe554e3ad535dc",
"sha256:b19e9f1b85c5d6136f5a0549abdc55dcbd63aba18b4f10d0d063eb65ef2c68b4",
"sha256:b664011bb14ca1f2287c17185e222f2098f7b4c857961dbcf9badb28786dbbf4",
"sha256:bde7959ef012b628868d69c474ec4920252656d0800835ed999ba5e4f57e3e2e",
"sha256:cb095a0657d792c8de9f7c9a0452385a309dfb1bbbb3357d6b1e216353ade6ca",
"sha256:d16d42a1b9772152c1fe606f679b2316551f7e1a1ce273e7f808e82a136cdb3d",
"sha256:d444b1545430ffc1e7a24ce5a9be122ccd3b135a7b7e695c5862c5aff0b11159",
"sha256:d93ccc7bf409ec0a23f2ac70977507e0b8a8d8c54e5ee46109af2f0ec9e411f3",
"sha256:df6444f952ca849016902662e1a47abf4fa0678d75f92fd9dd27f20525f809cd",
"sha256:e63850d8c52ba2b502662bf3c02603175c2397a9acc756090e444ce49508d41e",
"sha256:ec43358c105794bc2b6fd34c68d27f92bea7102393c01889e93f4b6a70975728",
"sha256:f4c6926d9c03dadce7a3b378b40d2fea912c1344ef9b29869f984fb3d2a2420b"
"sha256:163d3ee445a0b4c0109877da9e46271aacf4e5e3d60ae7368669555c30f13e7c",
"sha256:1af0bfe7b0c13a0e613a27311fd4f9c5d024e8fc0f4b3d284e7df02a58a11fc0",
"sha256:2169c3a1bf52d5b30cc98625b5919a964c571a32e8646be20be6c7e3e82079de",
"sha256:218f079fa48e2ef812dc3d3ce6ec2f67ac56427ba4b038d5d6331f2cceb489c2",
"sha256:26a958930687e94c4c6c73c171e4d4783b82ae4e16aa3424e6bcd4529bceedf0",
"sha256:2c7c195aef3acdbc853942bc674844031a732890d2fee88a324298ed376b6c2b",
"sha256:2ecdbfed7004669472bfa27c8d51012c717c241c7154ae17e4c8f93024043525",
"sha256:345fc31b71a90ada1b51826537917b19a1af685a91c0f066787069c184d7d00f",
"sha256:378a06649503f548be5f1e9eec2e94cc1d6138250b82a08dcc6151bca8cec107",
"sha256:3f300bf2930e501dde09605de85cb2b84c2638e2c954be02a3c86f28176d3525",
"sha256:6c2f66c653ce8bbd7e789d0f7f92c3f9fea881b55226f0ae5ee550cce9e3cf0e",
"sha256:6fccbac2633831b877a8fbf865f7082d34895e82a015795a9f80f99a2efe2576",
"sha256:7a166f8ccb6888358d3e67795b057540ea7caa71ab9e089b0cb0097f01088965",
"sha256:8f6b84f887ec6fef6c1796779f8ec2603dc7e9ef52bc9269de719d4bcbdaebbb",
"sha256:92cf3ceb7bb90cf35b8bd993c640b15d4832ba0e142a3b9da5006ef217da595d",
"sha256:a20dfdf73f56da674926a3811929cff9fd23b9af90be9a6c36ac246a3486eef3",
"sha256:a84415df4689251556c961e4fe3b25d30e32f00faa8064ce0909458dbe0d67b2",
"sha256:ab1aa1cd50df3860f624c9713ee9e690eefd4e049d3a4d86577bab6e741e9616",
"sha256:abc9dcf85e75a8687f2a6d560c0c1a2593e8e34ba6f9ad6721f8212c5de179a2",
"sha256:c10454710a81a2f4b1ff4d1c83ac2cec63e0e55845a56324991514af5b1299d0",
"sha256:c38f80719e4dfae7a6311a4f091f07f4fb2fb5d602352015d5639f63f8fabb68",
"sha256:d75cf00605630b2cfefa5c62373c605dcda1cc0d607902847dbb8e8e9b67c1ce",
"sha256:dce15cb6ef604c9e38fdaa848f58f83153ade9f4aa5e4cf5812aa27163561750",
"sha256:e7e0db4311bb76bf3f6e0380f71912cfa6d0be7cc635e3772476050b0dabdabd",
"sha256:eac59cae78dfe3fbf7ece25c170d7a152f88df7643381aa5e7344c2028a8d8d4",
"sha256:ead7b3e1567bd14cacd44279c5e42cd19f54b9feed39180220253f4fbe3abd56",
"sha256:ed772a5e8e7e5dd6bede960a86940c17cf653c7f158dafa5d52e919b676f10ba",
"sha256:f2d73131acb94afa45de8b6b8a4bfb21bbe3736633d6478e53247f19dd8c299c"
],
"version": "==2.7.7"
"version": "==2.8.1"
},
"pygithub": {
"hashes": [
"sha256:263102b43a83e2943900c1313109db7a00b3b78aeeae2c9137ba694982864872"
"sha256:74cbc6a0518bc7f4a8a1c047c954592abe622b735f1352ea30201668607fbe24"
],
"version": "==1.43.5"
"version": "==1.43.6"
},
"pyhamcrest": {
"hashes": [
@ -168,18 +173,25 @@
],
"version": "==1.7.1"
},
"python-http-client": {
"hashes": [
"sha256:7e430f4b9dd2b621b0051f6a362f103447ea8e267594c602a5c502a0c694ee38"
],
"version": "==3.1.0"
},
"redis": {
"hashes": [
"sha256:724932360d48e5407e8f82e405ab3650a36ed02c7e460d1e6fddf0f038422b54",
"sha256:9b19425a38fd074eb5795ff2b0d9a55b46a44f91f5347995f27e3ad257a7d775"
"sha256:6946b5dca72e86103edc8033019cc3814c031232d339d5f4533b02ea85685175",
"sha256:8ca418d2ddca1b1a850afa1680a7d2fd1f3322739271de4b704e0d4668449273"
],
"version": "==3.2.0"
"version": "==3.2.1"
},
"requests": {
"hashes": [
"sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e",
"sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"
],
"markers": "python_version >= '3.0'",
"version": "==2.21.0"
},
"schematics": {
@ -194,6 +206,13 @@
"editable": true,
"path": "./../../shared"
},
"sendgrid": {
"hashes": [
"sha256:351a7fc501d2b9d5afdcbc70a02490917057d6ce5cc22c558cadfc16229f157b",
"sha256:e1f93c72b3db3bd00d86f79ee926a093ee7e65533936a140855916569b08e0b0"
],
"version": "==6.0.4"
},
"six": {
"hashes": [
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
@ -201,6 +220,14 @@
],
"version": "==1.12.0"
},
"stripe": {
"hashes": [
"sha256:337149778e544c03d7a69da387b1ada1297c5878891dfa569e482c5433997e80",
"sha256:3f7eac3b55035071cc0142315aea976cc36dae61525223f0d3030450e9587f76"
],
"index": "pypi",
"version": "==2.24.0"
},
"urllib3": {
"hashes": [
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",
@ -217,10 +244,10 @@
},
"werkzeug": {
"hashes": [
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
"sha256:0a73e8bb2ff2feecfc5d56e6f458f5b99290ef34f565ffb2665801ff7de6af7a",
"sha256:7fad9770a8778f9576693f0cc29c7dcc36964df916b83734f4431c0e612a7fbc"
],
"version": "==0.14.1"
"version": "==0.15.2"
},
"wrapt": {
"hashes": [
@ -240,9 +267,9 @@
},
"parse": {
"hashes": [
"sha256:870dd675c1ee8951db3e29b81ebe44fd131e3eb8c03a79483a58ea574f3145c2"
"sha256:1b68657434d371e5156048ca4a0c5aea5afc6ca59a2fea4dd1a575354f617142"
],
"version": "==1.11.1"
"version": "==1.12.0"
},
"parse-type": {
"hashes": [

View File

@ -73,6 +73,11 @@ acct.add_url_rule(
view_func=device_endpoint,
methods=['GET', 'POST']
)
acct.add_url_rule(
'/api/devices/<string:device_id>',
view_func=device_endpoint,
methods=['DELETE']
)
device_count_endpoint = DeviceCountEndpoint.as_view('device_count_endpoint')
acct.add_url_rule(

View File

@ -176,3 +176,14 @@ class DeviceEndpoint(SeleneEndpoint):
value=json.dumps(pairing_data),
expiration=ONE_DAY
)
def delete(self, device_id):
self._authenticate()
self._delete_device(device_id)
return '', HTTPStatus.NO_CONTENT
def _delete_device(self, device_id):
with get_db_connection(self.config['DB_CONNECTION_POOL']) as db:
device_repository = DeviceRepository(db)
device_repository.remove(device_id)

View File

@ -21,7 +21,7 @@ class SkillsEndpoint(SeleneEndpoint):
for skill in skills:
response_data.append(dict(
id=skill.id,
name=skill.family_name,
name=skill.display_name or skill.family_name,
has_settings=skill.has_settings
))

View File

@ -8,7 +8,6 @@ flask = "*"
certifi = "*"
selene = {editable = true,path = "./../../shared"}
uwsgi = "*"
facebook-sdk = "*"
[dev-packages]
behave = "*"

95
api/sso/Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "21d28bfb59c70f15c40f43a13d422438da432b1c15f49b67358012107a1e03b4"
"sha256": "8a88efc755cb5bfcda2c6e9db57fb62a506e475386cdcda3da69435427d0a2fe"
},
"pipfile-spec": 6,
"requires": {
@ -50,7 +50,6 @@
"sha256:2e987b3e0f466a6f4ee77b935eb023dba1384134f004a2af21f1cfff7fe0806e",
"sha256:cabcd2e69ea3d9f042919c99b353df7aa1e2be86d040121f6e9f5e63c1cf0f8d"
],
"index": "pypi",
"version": "==3.1.0"
},
"flask": {
@ -77,10 +76,10 @@
},
"jinja2": {
"hashes": [
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
"sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
"sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
],
"version": "==2.10"
"version": "==2.10.1"
},
"markupsafe": {
"hashes": [
@ -124,44 +123,42 @@
},
"psycopg2-binary": {
"hashes": [
"sha256:19a2d1f3567b30f6c2bb3baea23f74f69d51f0c06c2e2082d0d9c28b0733a4c2",
"sha256:2b69cf4b0fa2716fd977aa4e1fd39af6110eb47b2bb30b4e5a469d8fbecfc102",
"sha256:2e952fa17ba48cbc2dc063ddeec37d7dc4ea0ef7db0ac1eda8906365a8543f31",
"sha256:348b49dd737ff74cfb5e663e18cb069b44c64f77ec0523b5794efafbfa7df0b8",
"sha256:3d72a5fdc5f00ca85160915eb9a973cf9a0ab8148f6eda40708bf672c55ac1d1",
"sha256:4957452f7868f43f32c090dadb4188e9c74a4687323c87a882e943c2bd4780c3",
"sha256:5138cec2ee1e53a671e11cc519505eb08aaaaf390c508f25b09605763d48de4b",
"sha256:587098ca4fc46c95736459d171102336af12f0d415b3b865972a79c03f06259f",
"sha256:5b79368bcdb1da4a05f931b62760bea0955ee2c81531d8e84625df2defd3f709",
"sha256:5cf43807392247d9bc99737160da32d3fa619e0bfd85ba24d1c78db205f472a4",
"sha256:676d1a80b1eebc0cacae8dd09b2fde24213173bf65650d22b038c5ed4039f392",
"sha256:6b0211ecda389101a7d1d3df2eba0cf7ffbdd2480ca6f1d2257c7bd739e84110",
"sha256:79cde4660de6f0bb523c229763bd8ad9a93ac6760b72c369cf1213955c430934",
"sha256:7aba9786ac32c2a6d5fb446002ed936b47d5e1f10c466ef7e48f66eb9f9ebe3b",
"sha256:7c8159352244e11bdd422226aa17651110b600d175220c451a9acf795e7414e0",
"sha256:945f2eedf4fc6b2432697eb90bb98cc467de5147869e57405bfc31fa0b824741",
"sha256:96b4e902cde37a7fc6ab306b3ac089a3949e6ce3d824eeca5b19dc0bedb9f6e2",
"sha256:9a7bccb1212e63f309eb9fab47b6eaef796f59850f169a25695b248ca1bf681b",
"sha256:a3bfcac727538ec11af304b5eccadbac952d4cca1a551a29b8fe554e3ad535dc",
"sha256:b19e9f1b85c5d6136f5a0549abdc55dcbd63aba18b4f10d0d063eb65ef2c68b4",
"sha256:b664011bb14ca1f2287c17185e222f2098f7b4c857961dbcf9badb28786dbbf4",
"sha256:bde7959ef012b628868d69c474ec4920252656d0800835ed999ba5e4f57e3e2e",
"sha256:cb095a0657d792c8de9f7c9a0452385a309dfb1bbbb3357d6b1e216353ade6ca",
"sha256:d16d42a1b9772152c1fe606f679b2316551f7e1a1ce273e7f808e82a136cdb3d",
"sha256:d444b1545430ffc1e7a24ce5a9be122ccd3b135a7b7e695c5862c5aff0b11159",
"sha256:d93ccc7bf409ec0a23f2ac70977507e0b8a8d8c54e5ee46109af2f0ec9e411f3",
"sha256:df6444f952ca849016902662e1a47abf4fa0678d75f92fd9dd27f20525f809cd",
"sha256:e63850d8c52ba2b502662bf3c02603175c2397a9acc756090e444ce49508d41e",
"sha256:ec43358c105794bc2b6fd34c68d27f92bea7102393c01889e93f4b6a70975728",
"sha256:f4c6926d9c03dadce7a3b378b40d2fea912c1344ef9b29869f984fb3d2a2420b"
"sha256:163d3ee445a0b4c0109877da9e46271aacf4e5e3d60ae7368669555c30f13e7c",
"sha256:1af0bfe7b0c13a0e613a27311fd4f9c5d024e8fc0f4b3d284e7df02a58a11fc0",
"sha256:2169c3a1bf52d5b30cc98625b5919a964c571a32e8646be20be6c7e3e82079de",
"sha256:218f079fa48e2ef812dc3d3ce6ec2f67ac56427ba4b038d5d6331f2cceb489c2",
"sha256:26a958930687e94c4c6c73c171e4d4783b82ae4e16aa3424e6bcd4529bceedf0",
"sha256:2c7c195aef3acdbc853942bc674844031a732890d2fee88a324298ed376b6c2b",
"sha256:2ecdbfed7004669472bfa27c8d51012c717c241c7154ae17e4c8f93024043525",
"sha256:345fc31b71a90ada1b51826537917b19a1af685a91c0f066787069c184d7d00f",
"sha256:378a06649503f548be5f1e9eec2e94cc1d6138250b82a08dcc6151bca8cec107",
"sha256:3f300bf2930e501dde09605de85cb2b84c2638e2c954be02a3c86f28176d3525",
"sha256:6c2f66c653ce8bbd7e789d0f7f92c3f9fea881b55226f0ae5ee550cce9e3cf0e",
"sha256:6fccbac2633831b877a8fbf865f7082d34895e82a015795a9f80f99a2efe2576",
"sha256:7a166f8ccb6888358d3e67795b057540ea7caa71ab9e089b0cb0097f01088965",
"sha256:8f6b84f887ec6fef6c1796779f8ec2603dc7e9ef52bc9269de719d4bcbdaebbb",
"sha256:92cf3ceb7bb90cf35b8bd993c640b15d4832ba0e142a3b9da5006ef217da595d",
"sha256:a20dfdf73f56da674926a3811929cff9fd23b9af90be9a6c36ac246a3486eef3",
"sha256:a84415df4689251556c961e4fe3b25d30e32f00faa8064ce0909458dbe0d67b2",
"sha256:ab1aa1cd50df3860f624c9713ee9e690eefd4e049d3a4d86577bab6e741e9616",
"sha256:abc9dcf85e75a8687f2a6d560c0c1a2593e8e34ba6f9ad6721f8212c5de179a2",
"sha256:c10454710a81a2f4b1ff4d1c83ac2cec63e0e55845a56324991514af5b1299d0",
"sha256:c38f80719e4dfae7a6311a4f091f07f4fb2fb5d602352015d5639f63f8fabb68",
"sha256:d75cf00605630b2cfefa5c62373c605dcda1cc0d607902847dbb8e8e9b67c1ce",
"sha256:dce15cb6ef604c9e38fdaa848f58f83153ade9f4aa5e4cf5812aa27163561750",
"sha256:e7e0db4311bb76bf3f6e0380f71912cfa6d0be7cc635e3772476050b0dabdabd",
"sha256:eac59cae78dfe3fbf7ece25c170d7a152f88df7643381aa5e7344c2028a8d8d4",
"sha256:ead7b3e1567bd14cacd44279c5e42cd19f54b9feed39180220253f4fbe3abd56",
"sha256:ed772a5e8e7e5dd6bede960a86940c17cf653c7f158dafa5d52e919b676f10ba",
"sha256:f2d73131acb94afa45de8b6b8a4bfb21bbe3736633d6478e53247f19dd8c299c"
],
"version": "==2.7.7"
"version": "==2.8.1"
},
"pygithub": {
"hashes": [
"sha256:263102b43a83e2943900c1313109db7a00b3b78aeeae2c9137ba694982864872"
"sha256:74cbc6a0518bc7f4a8a1c047c954592abe622b735f1352ea30201668607fbe24"
],
"version": "==1.43.5"
"version": "==1.43.6"
},
"pyhamcrest": {
"hashes": [
@ -211,10 +208,10 @@
},
"sendgrid": {
"hashes": [
"sha256:97eb356ea44a18a03e6fe99f02b7942445be306a50f73a7dd35471fe15cc0094",
"sha256:9e9d3d75602b8853f174ec959d1af1ac168cd361cbcafc81285fa8c183f7a505"
"sha256:351a7fc501d2b9d5afdcbc70a02490917057d6ce5cc22c558cadfc16229f157b",
"sha256:e1f93c72b3db3bd00d86f79ee926a093ee7e65533936a140855916569b08e0b0"
],
"version": "==5.6.0"
"version": "==6.0.4"
},
"six": {
"hashes": [
@ -225,10 +222,10 @@
},
"stripe": {
"hashes": [
"sha256:191f6c3f5b0750ab2e1410a3fedb22001b34afe351728ac0019e281415569806",
"sha256:a973c2225faeb062bc33e9fdc936fce9229e507bba4b34c05e2b918503b8a033"
"sha256:337149778e544c03d7a69da387b1ada1297c5878891dfa569e482c5433997e80",
"sha256:3f7eac3b55035071cc0142315aea976cc36dae61525223f0d3030450e9587f76"
],
"version": "==2.23.0"
"version": "==2.24.0"
},
"urllib3": {
"hashes": [
@ -246,10 +243,10 @@
},
"werkzeug": {
"hashes": [
"sha256:96da23fa8ccecbc3ae832a83df5c722c11547d021637faacb0bec4dd2f4666c8",
"sha256:ca5c2dcd367d6c0df87185b9082929d255358f5391923269335782b213d52655"
"sha256:0a73e8bb2ff2feecfc5d56e6f458f5b99290ef34f565ffb2665801ff7de6af7a",
"sha256:7fad9770a8778f9576693f0cc29c7dcc36964df916b83734f4431c0e612a7fbc"
],
"version": "==0.15.1"
"version": "==0.15.2"
},
"wrapt": {
"hashes": [
@ -269,9 +266,9 @@
},
"parse": {
"hashes": [
"sha256:870dd675c1ee8951db3e29b81ebe44fd131e3eb8c03a79483a58ea574f3145c2"
"sha256:1b68657434d371e5156048ca4a0c5aea5afc6ca59a2fea4dd1a575354f617142"
],
"version": "==1.11.1"
"version": "==1.12.0"
},
"parse-type": {
"hashes": [

View File

@ -8,13 +8,13 @@ on our database and build JWTs for access and refresh.
from http import HTTPStatus
from logging import getLogger
from facebook import GraphAPI
from flask import json
import requests
from selene.api import SeleneEndpoint
from selene.data.account import AccountRepository, RefreshTokenRepository
from selene.util.auth import AuthenticationError
from selene.util.auth import (
AuthenticationError,
get_facebook_account_email,
get_google_account_email
)
from selene.util.db import get_db_connection
_log = getLogger()
@ -37,26 +37,14 @@ class ValidateFederatedEndpoint(SeleneEndpoint):
return self.response
def _get_email_address(self):
request_data = json.loads(self.request.data)
if request_data['platform'] == 'Google':
self._get_email_from_google(request_data['token'])
elif request_data['platform'] == 'Facebook':
self._get_email_from_facebook(request_data['token'])
def _get_email_from_google(self, token):
google_response = requests.get(
'https://oauth2.googleapis.com/tokeninfo?id_token=' + token
)
if google_response.status_code == HTTPStatus.OK:
google_account = json.loads(google_response.content)
self.email_address = google_account['email']
else:
raise AuthenticationError('invalid Google token')
def _get_email_from_facebook(self, token):
facebook_api = GraphAPI(token)
facebook_account = facebook_api.get_object(id='me?fields=email')
self.email_address = facebook_account['email']
if self.request.json['platform'] == 'Google':
self.email_address = get_google_account_email(
self.request.json['token']
)
elif self.request.json['platform'] == 'Facebook':
self.email_address = get_facebook_account_email(
self.request.json['token']
)
def _get_account_by_email(self):
"""Use email returned by the authentication platform for validation"""

View File

@ -4,6 +4,7 @@ verify_ssl = true
name = "pypi"
[packages]
facebook-sdk = "*"
pyjwt = "*"
pygithub = "*"
psycopg2-binary = "*"

86
shared/Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "aed1f40f8d3b4395db3eb673164c87a2a43f461bc08c60dace04edd6c838085e"
"sha256": "85edb2ac854a79ba22f23fe4b37784c9344e4da81b4a115bc871983e46f88a16"
},
"pipfile-spec": 6,
"requires": {
@ -37,6 +37,14 @@
],
"version": "==1.2.5"
},
"facebook-sdk": {
"hashes": [
"sha256:2e987b3e0f466a6f4ee77b935eb023dba1384134f004a2af21f1cfff7fe0806e",
"sha256:cabcd2e69ea3d9f042919c99b353df7aa1e2be86d040121f6e9f5e63c1cf0f8d"
],
"index": "pypi",
"version": "==3.1.0"
},
"idna": {
"hashes": [
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
@ -54,46 +62,44 @@
},
"psycopg2-binary": {
"hashes": [
"sha256:19a2d1f3567b30f6c2bb3baea23f74f69d51f0c06c2e2082d0d9c28b0733a4c2",
"sha256:2b69cf4b0fa2716fd977aa4e1fd39af6110eb47b2bb30b4e5a469d8fbecfc102",
"sha256:2e952fa17ba48cbc2dc063ddeec37d7dc4ea0ef7db0ac1eda8906365a8543f31",
"sha256:348b49dd737ff74cfb5e663e18cb069b44c64f77ec0523b5794efafbfa7df0b8",
"sha256:3d72a5fdc5f00ca85160915eb9a973cf9a0ab8148f6eda40708bf672c55ac1d1",
"sha256:4957452f7868f43f32c090dadb4188e9c74a4687323c87a882e943c2bd4780c3",
"sha256:5138cec2ee1e53a671e11cc519505eb08aaaaf390c508f25b09605763d48de4b",
"sha256:587098ca4fc46c95736459d171102336af12f0d415b3b865972a79c03f06259f",
"sha256:5b79368bcdb1da4a05f931b62760bea0955ee2c81531d8e84625df2defd3f709",
"sha256:5cf43807392247d9bc99737160da32d3fa619e0bfd85ba24d1c78db205f472a4",
"sha256:676d1a80b1eebc0cacae8dd09b2fde24213173bf65650d22b038c5ed4039f392",
"sha256:6b0211ecda389101a7d1d3df2eba0cf7ffbdd2480ca6f1d2257c7bd739e84110",
"sha256:79cde4660de6f0bb523c229763bd8ad9a93ac6760b72c369cf1213955c430934",
"sha256:7aba9786ac32c2a6d5fb446002ed936b47d5e1f10c466ef7e48f66eb9f9ebe3b",
"sha256:7c8159352244e11bdd422226aa17651110b600d175220c451a9acf795e7414e0",
"sha256:945f2eedf4fc6b2432697eb90bb98cc467de5147869e57405bfc31fa0b824741",
"sha256:96b4e902cde37a7fc6ab306b3ac089a3949e6ce3d824eeca5b19dc0bedb9f6e2",
"sha256:9a7bccb1212e63f309eb9fab47b6eaef796f59850f169a25695b248ca1bf681b",
"sha256:a3bfcac727538ec11af304b5eccadbac952d4cca1a551a29b8fe554e3ad535dc",
"sha256:b19e9f1b85c5d6136f5a0549abdc55dcbd63aba18b4f10d0d063eb65ef2c68b4",
"sha256:b664011bb14ca1f2287c17185e222f2098f7b4c857961dbcf9badb28786dbbf4",
"sha256:bde7959ef012b628868d69c474ec4920252656d0800835ed999ba5e4f57e3e2e",
"sha256:cb095a0657d792c8de9f7c9a0452385a309dfb1bbbb3357d6b1e216353ade6ca",
"sha256:d16d42a1b9772152c1fe606f679b2316551f7e1a1ce273e7f808e82a136cdb3d",
"sha256:d444b1545430ffc1e7a24ce5a9be122ccd3b135a7b7e695c5862c5aff0b11159",
"sha256:d93ccc7bf409ec0a23f2ac70977507e0b8a8d8c54e5ee46109af2f0ec9e411f3",
"sha256:df6444f952ca849016902662e1a47abf4fa0678d75f92fd9dd27f20525f809cd",
"sha256:e63850d8c52ba2b502662bf3c02603175c2397a9acc756090e444ce49508d41e",
"sha256:ec43358c105794bc2b6fd34c68d27f92bea7102393c01889e93f4b6a70975728",
"sha256:f4c6926d9c03dadce7a3b378b40d2fea912c1344ef9b29869f984fb3d2a2420b"
"sha256:163d3ee445a0b4c0109877da9e46271aacf4e5e3d60ae7368669555c30f13e7c",
"sha256:1af0bfe7b0c13a0e613a27311fd4f9c5d024e8fc0f4b3d284e7df02a58a11fc0",
"sha256:2169c3a1bf52d5b30cc98625b5919a964c571a32e8646be20be6c7e3e82079de",
"sha256:218f079fa48e2ef812dc3d3ce6ec2f67ac56427ba4b038d5d6331f2cceb489c2",
"sha256:26a958930687e94c4c6c73c171e4d4783b82ae4e16aa3424e6bcd4529bceedf0",
"sha256:2c7c195aef3acdbc853942bc674844031a732890d2fee88a324298ed376b6c2b",
"sha256:2ecdbfed7004669472bfa27c8d51012c717c241c7154ae17e4c8f93024043525",
"sha256:345fc31b71a90ada1b51826537917b19a1af685a91c0f066787069c184d7d00f",
"sha256:378a06649503f548be5f1e9eec2e94cc1d6138250b82a08dcc6151bca8cec107",
"sha256:3f300bf2930e501dde09605de85cb2b84c2638e2c954be02a3c86f28176d3525",
"sha256:6c2f66c653ce8bbd7e789d0f7f92c3f9fea881b55226f0ae5ee550cce9e3cf0e",
"sha256:6fccbac2633831b877a8fbf865f7082d34895e82a015795a9f80f99a2efe2576",
"sha256:7a166f8ccb6888358d3e67795b057540ea7caa71ab9e089b0cb0097f01088965",
"sha256:8f6b84f887ec6fef6c1796779f8ec2603dc7e9ef52bc9269de719d4bcbdaebbb",
"sha256:92cf3ceb7bb90cf35b8bd993c640b15d4832ba0e142a3b9da5006ef217da595d",
"sha256:a20dfdf73f56da674926a3811929cff9fd23b9af90be9a6c36ac246a3486eef3",
"sha256:a84415df4689251556c961e4fe3b25d30e32f00faa8064ce0909458dbe0d67b2",
"sha256:ab1aa1cd50df3860f624c9713ee9e690eefd4e049d3a4d86577bab6e741e9616",
"sha256:abc9dcf85e75a8687f2a6d560c0c1a2593e8e34ba6f9ad6721f8212c5de179a2",
"sha256:c10454710a81a2f4b1ff4d1c83ac2cec63e0e55845a56324991514af5b1299d0",
"sha256:c38f80719e4dfae7a6311a4f091f07f4fb2fb5d602352015d5639f63f8fabb68",
"sha256:d75cf00605630b2cfefa5c62373c605dcda1cc0d607902847dbb8e8e9b67c1ce",
"sha256:dce15cb6ef604c9e38fdaa848f58f83153ade9f4aa5e4cf5812aa27163561750",
"sha256:e7e0db4311bb76bf3f6e0380f71912cfa6d0be7cc635e3772476050b0dabdabd",
"sha256:eac59cae78dfe3fbf7ece25c170d7a152f88df7643381aa5e7344c2028a8d8d4",
"sha256:ead7b3e1567bd14cacd44279c5e42cd19f54b9feed39180220253f4fbe3abd56",
"sha256:ed772a5e8e7e5dd6bede960a86940c17cf653c7f158dafa5d52e919b676f10ba",
"sha256:f2d73131acb94afa45de8b6b8a4bfb21bbe3736633d6478e53247f19dd8c299c"
],
"index": "pypi",
"version": "==2.7.7"
"version": "==2.8.1"
},
"pygithub": {
"hashes": [
"sha256:263102b43a83e2943900c1313109db7a00b3b78aeeae2c9137ba694982864872"
"sha256:74cbc6a0518bc7f4a8a1c047c954592abe622b735f1352ea30201668607fbe24"
],
"index": "pypi",
"version": "==1.43.5"
"version": "==1.43.6"
},
"pyhamcrest": {
"hashes": [
@ -143,11 +149,11 @@
},
"sendgrid": {
"hashes": [
"sha256:97eb356ea44a18a03e6fe99f02b7942445be306a50f73a7dd35471fe15cc0094",
"sha256:9e9d3d75602b8853f174ec959d1af1ac168cd361cbcafc81285fa8c183f7a505"
"sha256:351a7fc501d2b9d5afdcbc70a02490917057d6ce5cc22c558cadfc16229f157b",
"sha256:e1f93c72b3db3bd00d86f79ee926a093ee7e65533936a140855916569b08e0b0"
],
"index": "pypi",
"version": "==5.6.0"
"version": "==6.0.4"
},
"six": {
"hashes": [
@ -158,11 +164,11 @@
},
"stripe": {
"hashes": [
"sha256:191f6c3f5b0750ab2e1410a3fedb22001b34afe351728ac0019e281415569806",
"sha256:a973c2225faeb062bc33e9fdc936fce9229e507bba4b34c05e2b918503b8a033"
"sha256:337149778e544c03d7a69da387b1ada1297c5878891dfa569e482c5433997e80",
"sha256:3f7eac3b55035071cc0142315aea976cc36dae61525223f0d3030450e9587f76"
],
"index": "pypi",
"version": "==2.23.0"
"version": "==2.24.0"
},
"urllib3": {
"hashes": [

View File

@ -18,6 +18,10 @@ from selene.data.account import (
PRIVACY_POLICY,
TERMS_OF_USE,
MembershipRepository)
from selene.util.auth import (
get_facebook_account_email,
get_google_account_email
)
from selene.util.db import get_db_connection
from selene.util.payment import (
cancel_stripe_subscription,
@ -37,12 +41,13 @@ def agreement_accepted(value):
class Login(Model):
federated_email = EmailType()
federated_platform = StringType(choices=['Facebook', 'Google'])
federated_token = StringType()
user_entered_email = EmailType()
password = StringType()
def validate_user_entered_email(self, data, value):
if data['federated_email'] is None:
if data['federated_token'] is None:
if value is None:
raise ValidationError(
'either a federated login or an email address is required'
@ -172,7 +177,8 @@ class AccountEndpoint(SeleneEndpoint):
login_data = self.request_data['login']
if login_data is not None:
login = Login(dict(
federated_email=login_data.get('federatedEmail'),
federated_platform=login_data.get('federatedPlatform'),
federated_token=login_data.get('federatedToken'),
user_entered_email=login_data.get('userEnteredEmail'),
password=login_data.get('password')
))
@ -194,12 +200,18 @@ class AccountEndpoint(SeleneEndpoint):
def _determine_login_method(self):
login_data = self.request_data['login']
if login_data['federatedEmail'] is None:
password = None
if login_data['federatedPlatform'] == 'Facebook':
email_address = get_facebook_account_email(
login_data['federatedToken']
)
elif login_data['federatedPlatform'] == 'Google':
email_address = get_google_account_email(
login_data['federatedToken']
)
else:
email_address = login_data['userEnteredEmail']
password = login_data['password']
else:
email_address = login_data['federatedEmail']
password = None
return email_address, password

View File

@ -1,18 +1,15 @@
from os import path
from typing import List
from selene.util.db import DatabaseRequest, get_sql_from_file, Cursor
from ..entity.device import Device
from ..entity.geography import Geography
from ..entity.text_to_speech import TextToSpeech
from ..entity.wake_word import WakeWord
SQL_DIR = path.join(path.dirname(__file__), 'sql')
from ...repository_base import RepositoryBase
class DeviceRepository(object):
class DeviceRepository(RepositoryBase):
def __init__(self, db):
self.cursor = Cursor(db)
super(DeviceRepository, self).__init__(db, __file__)
def get_device_by_id(self, device_id: str) -> dict:
"""Fetch a device using a given device id
@ -20,12 +17,12 @@ class DeviceRepository(object):
:param device_id: uuid
:return: Device entity
"""
query = DatabaseRequest(
sql=get_sql_from_file(path.join(SQL_DIR, 'get_device_by_id.sql')),
db_request = self._build_db_request(
sql_file_name='get_device_by_id.sql',
args=dict(device_id=device_id)
)
return self.cursor.select_one(query)
return self.cursor.select_one(db_request)
def get_devices_by_account_id(self, account_id: str) -> List[Device]:
"""Fetch all devices associated to a user from a given account id
@ -33,10 +30,8 @@ class DeviceRepository(object):
:param account_id: uuid
:return: List of User's devices
"""
db_request = DatabaseRequest(
sql=get_sql_from_file(
path.join(SQL_DIR, 'get_devices_by_account_id.sql')
),
db_request = self._build_db_request(
sql_file_name='get_devices_by_account_id.sql',
args=dict(account_id=account_id)
)
db_results = self.cursor.select_all(db_request)
@ -51,28 +46,25 @@ class DeviceRepository(object):
return devices
def get_account_device_count(self, account_id):
query = DatabaseRequest(
sql=get_sql_from_file(
path.join(SQL_DIR, 'get_account_device_count.sql')
),
db_request = self._build_db_request(
sql_file_name='get_account_device_count.sql',
args=dict(account_id=account_id)
)
sql_results = self.cursor.select_one(query)
db_results = self.cursor.select_one(db_request)
return sql_results['device_count']
return db_results['device_count']
def get_subscription_type_by_device_id(self, device_id):
"""Return the type of subscription of device's owner
:param device_id: device uuid
"""
query = DatabaseRequest(
sql=get_sql_from_file(path.join(SQL_DIR, 'get_subscription_type_by_device_id.sql')),
db_request = self._build_db_request(
sql_file_name='get_subscription_type_by_device_id.sql',
args=dict(device_id=device_id)
)
sql_result = self.cursor.select_one(query)
if sql_result:
rate_period = sql_result['rate_period']
db_result = self.cursor.select_one(db_request)
if db_result:
rate_period = db_result['rate_period']
# TODO: Remove the @ in the API v2
return {'@type': rate_period} if rate_period is not None else {'@type': 'free'}
@ -81,17 +73,17 @@ class DeviceRepository(object):
db_request_args = dict(account_id=account_id)
db_request_args.update(device)
del(db_request_args['pairing_code'])
query = DatabaseRequest(
sql=get_sql_from_file(path.join(SQL_DIR, 'add_device.sql')),
db_request = self._build_db_request(
sql_file_name='add_device.sql',
args=db_request_args
)
result = self.cursor.insert_returning(query)
return result['id']
db_result = self.cursor.insert_returning(db_request)
return db_result['id']
def update_device(self, device_id: str, platform: str, enclosure_version: str, core_version: str):
"""Updates a device in the database"""
query = DatabaseRequest(
sql=get_sql_from_file(path.join(SQL_DIR, 'update_device.sql')),
db_request =self._build_db_request(
sql_file_name='update_device.sql',
args=dict(
device_id=device_id,
platform=platform,
@ -99,16 +91,17 @@ class DeviceRepository(object):
core_version=core_version
)
)
return self.cursor.insert(query)
return self.cursor.insert(db_request)
def add_wake_word(self, account_id: str, wake_word: WakeWord) -> str:
"""Adds a row to the wake word table
:param account_id: the account that we are linking to the wake word
:param wake_word: wake_word entity
:return wake word id
"""
query = DatabaseRequest(
sql=get_sql_from_file(path.join(SQL_DIR, 'add_wake_word.sql')),
db_request = self._build_db_request(
sql_file_name='add_wake_word.sql',
args=dict(
setting_name=wake_word.setting_name,
display_name=wake_word.display_name,
@ -116,36 +109,47 @@ class DeviceRepository(object):
engine=wake_word.engine
)
)
result = self.cursor.insert_returning(query)
result = self.cursor.insert_returning(db_request)
return result['id']
def add_text_to_speech(self, text_to_speech: TextToSpeech) -> str:
"""Add a row to the text to speech table
:param text_to_speech: text to speech entity
:return text to speech id"""
query = DatabaseRequest(
sql=get_sql_from_file(path.join(SQL_DIR, 'add_text_to_speech.sql')),
:return text to speech id
"""
db_request = self._build_db_request(
sql_file_name='add_text_to_speech.sql',
args=dict(
setting_name=text_to_speech.setting_name,
display_name=text_to_speech.display_name,
engine=text_to_speech.engine
)
)
result = self.cursor.insert_returning(query)
return result['id']
db_result = self.cursor.insert_returning(db_request)
return db_result['id']
def remove_wake_word(self, wake_word_id: str):
"""Remove a wake word from the database using id"""
query = DatabaseRequest(
sql=get_sql_from_file(path.join(SQL_DIR, 'remove_wake_word.sql')),
db_request = self._build_db_request(
sql_file_name='remove_wake_word.sql',
args=dict(wake_word_id=wake_word_id)
)
self.cursor.delete(query)
self.cursor.delete(db_request)
def remove_text_to_speech(self, text_to_speech_id: str):
"""Remove a text to speech from the database using id"""
query = DatabaseRequest(
sql=get_sql_from_file(path.join(SQL_DIR, 'remove_text_to_speech.sql')),
db_request = self._build_db_request(
sql_file_name='remove_text_to_speech.sql',
args=dict(text_to_speech_id=text_to_speech_id)
)
self.cursor.delete(query)
self.cursor.delete(db_request)
def remove(self, device_id):
db_request = self._build_db_request(
sql_file_name='remove_device.sql',
args=dict(device_id=device_id)
)
self.cursor.delete(db_request)

View File

@ -0,0 +1,4 @@
DELETE FROM
device.device
WHERE
id = %(device_id)s

View File

@ -39,6 +39,7 @@ class SkillVersion(object):
@dataclass
class Skill(object):
skill_gid: str
display_name: str = None
family_name: str = None
has_settings: bool = None
id: str = None

View File

@ -1,25 +1,28 @@
WITH
setting_meta AS (
setting_display AS (
SELECT
s.id,
count(sd.id) > 0 AS has_settings
sd.settings_display -> 'display_name' AS display_name,
sd.settings_display -> 'skillMetadata' IS NOT NULL AS has_settings
FROM
skill.skill s
LEFT JOIN skill.settings_display sd ON s.id = sd.skill_id
GROUP BY
s.id
s.id,
settings_display
)
SELECT DISTINCT
json_build_object(
'id', s.id,
'skill_gid', s.skill_gid,
'family_name', s.family_name,
'has_settings', sm.has_settings
'has_settings', sm.has_settings,
'display_name', sm.display_name
)::jsonb as skill
FROM
skill.skill s
INNER JOIN device.device_skill ds ON ds.skill_id = s.id
INNER JOIN device.device d ON d.id = ds.device_id
INNER JOIN setting_meta sm ON sm.id = s.id
INNER JOIN setting_display sm ON sm.id = s.id
WHERE
d.account_id = %(account_id)s

View File

@ -1,8 +1,12 @@
"""Logic for generating and validating JWT authentication tokens."""
from datetime import datetime
from http import HTTPStatus
import json
from time import time
from facebook import GraphAPI
import jwt
import requests
class AuthenticationError(Exception):
@ -51,3 +55,23 @@ class AuthenticationToken(object):
self.is_valid = False
return account_id
def get_google_account_email(token):
google_response = requests.get(
'https://oauth2.googleapis.com/tokeninfo?id_token=' + token
)
if google_response.status_code == HTTPStatus.OK:
google_account = json.loads(google_response.content)
email_address = google_account['email']
else:
raise AuthenticationError('invalid Google token')
return email_address
def get_facebook_account_email(token):
facebook_api = GraphAPI(token)
facebook_account = facebook_api.get_object(id='me?fields=email')
return facebook_account['email']

View File

@ -10,6 +10,7 @@ setup(
packages=find_packages(),
include_package_data=True,
install_requires=[
'facebook-sdk',
'flask',
'passlib',
'pygithub',