Prepare for Telethon Authenticator

This commit is contained in:
David Todd 2020-01-19 00:20:40 -06:00
parent 4b613cb8d5
commit 68032742ba
5 changed files with 248 additions and 159 deletions

View File

@ -11,7 +11,7 @@ import datetime
from pprint import pprint from pprint import pprint
from uuid import UUID from uuid import UUID
from bottle import response, abort from bottle import response, abort
from .db import Database from .db import BookmarkDatabase, TelethonDatabase
class API: class API:
""" """
@ -26,7 +26,8 @@ class API:
Setup some internal variables, such as various constants Setup some internal variables, such as various constants
and the database connection and the database connection
""" """
self.database = Database('bookmarks.db') self.bookmark_database = BookmarkDatabase('database.db')
self.telethon_database = TelethonDatabase('database.db')
self.dt_fmt = "%H:%M:%S on %B %d %Y" self.dt_fmt = "%H:%M:%S on %B %d %Y"
self.response_type = 'application/json' self.response_type = 'application/json'
self.format_date = datetime.datetime.strftime self.format_date = datetime.datetime.strftime
@ -52,7 +53,7 @@ class API:
the UUID of the saved bookmark the UUID of the saved bookmark
""" """
response.content_type = self.response_type response.content_type = self.response_type
bookmark = self.database.save_bookmark(uri, title) bookmark = self.bookmark_database.save_bookmark(uri, title)
return json.dumps({ return json.dumps({
'uuid': bookmark.hex 'uuid': bookmark.hex
@ -67,7 +68,7 @@ class API:
everything about the bookmark everything about the bookmark
""" """
response.content_type = self.response_type response.content_type = self.response_type
bookmark = self.database.get_bookmark(UUID(bookmark_id)) bookmark = self.bookmark_database.get_bookmark(UUID(bookmark_id))
if bookmark == None: if bookmark == None:
return abort(404, "Provided bookmark doesn't exist or has been deleted") return abort(404, "Provided bookmark doesn't exist or has been deleted")
@ -82,7 +83,7 @@ class API:
everything about each bookmark everything about each bookmark
""" """
response.content_type = self.response_type response.content_type = self.response_type
bookmarks = self.database.get_all_bookmarks() bookmarks = self.bookmark_database.get_all_bookmarks()
if len(bookmarks) == 0: if len(bookmarks) == 0:
return abort(404, "There are no bookmarks saved") return abort(404, "There are no bookmarks saved")
@ -109,7 +110,7 @@ class API:
response.content_type = self.response_type response.content_type = self.response_type
return json.dumps({ return json.dumps({
'uuid': bookmark_id, 'uuid': bookmark_id,
'bookmark_deleted': self.database.delete_bookmark(UUID(bookmark_id)), 'bookmark_deleted': self.bookmark_database.delete_bookmark(UUID(bookmark_id)),
}) })
def update_bookmark_title(self, bookmark_id, title): def update_bookmark_title(self, bookmark_id, title):
@ -121,7 +122,7 @@ class API:
everything about the bookmark everything about the bookmark
""" """
response.content_type = self.response_type response.content_type = self.response_type
bookmark = self.database.update_bookmark_title(UUID(bookmark_id), title) bookmark = self.bookmark_database.update_bookmark_title(UUID(bookmark_id), title)
if bookmark == None: if bookmark == None:
return abort(404, "Provided bookmark doesn't exist or has been deleted") return abort(404, "Provided bookmark doesn't exist or has been deleted")
@ -142,7 +143,7 @@ class API:
"Perhaps you want to delete this bookmark instead?" "Perhaps you want to delete this bookmark instead?"
response.content_type = self.response_type response.content_type = self.response_type
bookmark = self.database.update_bookmark_uri(UUID(bookmark_id), uri) bookmark = self.bookmark_database.update_bookmark_uri(UUID(bookmark_id), uri)
if bookmark == None: if bookmark == None:
return abort(404, "Provided bookmark doesn't exist or has been deleted") return abort(404, "Provided bookmark doesn't exist or has been deleted")

View File

@ -7,3 +7,5 @@
""" """
from .db import Database from .db import Database
from .bookmark_db import BookmarkDatabase
from .telethon_db import TelethonDatabase

172
api/db/bookmark_db.py Normal file
View File

@ -0,0 +1,172 @@
#!/usr/bin/env python3
# Copyright 2020 - David Todd (c0de@c0defox.es)
# Licensed under the MIT License (https://opensource.org/licenses/MIT)
"""
This file contains the database for a simple bookmarking application
"""
import datetime
import sqlite3
import uuid
class BookmarkDatabase(Database):
"""
This class contains various methods for interacting
with the database for the bookmarking engine.
"""
def __init__(self, database):
"""
Sets up the database connection + cursor
as well as creates a new table if it doesn't
exist in the database that is provided via the
instantiation of this class
"""
super(BookmarkDatabase, self).__init__(database)
# Automatically create the table if it doesn't
# already exist in the selected database
self._create_table()
def _create_table(self):
"""
Creates a table called `bookmarks`
that uses UUID as the primary key.
The UUID is generated from the `uri`,
which will be updated in the case that
a bookmark's uri gets updated.
`title` is a short, human readable/recognizable
string.
`create_date` and `update_date` are the datetimes
that the entry was created and updated, respectively.
"""
query = """
CREATE TABLE IF NOT EXISTS bookmarks (
bookmark_id GUID PRIMARY KEY,
uri TEXT NOT NULL,
title TEXT NOT NULL,
create_date TIMESTAMP NOT NULL,
update_date TIMESTAMP
)
"""
self.cursor.execute(query)
self.connection.commit()
def get_all_bookmarks(self):
"""
Returns all bookmarks in the database as a list.
"""
query = "SELECT * FROM bookmarks"
self.cursor.execute(query)
return self.cursor.fetchall()
def get_bookmark(self, bookmark_id):
"""
With the provided `bookmark_id`, the database will be
searched for a matching entry, with the row returned
if there is a match. If there is no match, None will
be returned.
`bookmark_id` is of type uuid.UUID()
"""
query = "SELECT * FROM bookmarks WHERE bookmark_id = ?"
self.cursor.execute(query, (bookmark_id, ))
return self.cursor.fetchone()
def save_bookmark(self, uri, title):
"""
Determines if the provided `uri` doesn't already
exist in the database adding a new entry if that
is the case. If the `uri` is already stored
(based on the generated UUID), the existing
entry's UUID will be returned instead.
"""
uri_uuid = uuid.uuid5(uuid.NAMESPACE_URL, uri)
bookmark_exists = self.get_bookmark(uri_uuid)
if bookmark_exists != None:
return bookmark_exists[0]
query = """
INSERT INTO bookmarks (
bookmark_id, uri, title, create_date
) VALUES (?, ?, ?, ?)
"""
self.cursor.execute(query, (uri_uuid, uri, title, datetime.datetime.now()))
self.connection.commit()
return uri_uuid
def delete_bookmark(self, bookmark_id):
"""
Removes the bookmark entry if it exists
`bookmark_id` is of type uuid.UUID()
Returns True upon successful removal.
Returns False upon unsuccessful removal.
"""
if self.get_bookmark(bookmark_id) != None:
query = "DELETE FROM bookmarks WHERE bookmark_id = ?"
self.cursor.execute(query, (bookmark_id, ))
self.connection.commit()
if self.get_bookmark(bookmark_id) == None:
return True
return False
def update_bookmark_title(self, bookmark_id, new_title):
"""
Takes the provided `bookmark_id`, searches the
database for the matching record, and if found
the title will be replaced with `new_title`.
`bookmark_id` is of type uuid.UUID()
Returns None if there is no matching bookmark.
"""
bookmark = self.get_bookmark(bookmark_id)
if bookmark != None:
query = """
UPDATE bookmarks
SET title = ?, update_date = ?
WHERE bookmark_id = ?
"""
self.cursor.execute(query, (new_title, datetime.datetime.now(), bookmark_id, ))
self.connection.commit()
return self.get_bookmark(bookmark_id)
return None
def update_bookmark_uri(self, bookmark_id, new_uri):
"""
Takes the provided `bookmark_id`, searches the
database for the matching record, and if found
the URI will be replaced with `new_uri`.
`bookmark_id` is of type uuid.UUID()
A new `bookmark_id` will be generated if the
`new_uri` is different than what was previously
stored. If the newly generated `bookmark_id` matches
an existing entry, this method will return False.
You may want to delete the old bookmark in this case.
Returns None if there is no matching bookmark.
"""
bookmark = self.get_bookmark(bookmark_id)
if bookmark != None:
query = """
UPDATE bookmarks
SET bookmark_id = ?, uri = ?, update_date = ?
WHERE bookmark_id = ?
"""
new_bookmark_id = uuid.uuid5(uuid.NAMESPACE_URL, new_uri)
if self.get_bookmark(new_bookmark_id) == None:
self.cursor.execute(query, (new_bookmark_id, new_uri, datetime.datetime.now(), bookmark_id, ))
self.connection.commit()
return self.get_bookmark(new_bookmark_id)
return False
return None

View File

@ -9,11 +9,10 @@
import datetime import datetime
import sqlite3 import sqlite3
import uuid import uuid
class Database: class Database:
""" """
This class contains various methods for interacting Base database class that is shared by the bookmark
with the database for the bookmarking engine. engine and the Telethon authenticator
""" """
def __init__(self, database): def __init__(self, database):
@ -36,151 +35,3 @@ class Database:
self.connection = sqlite3.connect(database, detect_types=detect_types) self.connection = sqlite3.connect(database, detect_types=detect_types)
with self.connection: with self.connection:
self.cursor = self.connection.cursor() self.cursor = self.connection.cursor()
# Automatically create the table if it doesn't
# already exist in the selected database
self._create_table()
def _create_table(self):
"""
Creates a table called `bookmarks`
that uses UUID as the primary key.
The UUID is generated from the `uri`,
which will be updated in the case that
a bookmark's uri gets updated.
`title` is a short, human readable/recognizable
string.
`create_date` and `update_date` are the datetimes
that the entry was create and updated, respectively.
"""
query = """
CREATE TABLE IF NOT EXISTS bookmarks (
bookmark_id GUID PRIMARY KEY,
uri TEXT NOT NULL,
title TEXT NOT NULL,
create_date TIMESTAMP NOT NULL,
update_date TIMESTAMP
)
"""
self.cursor.execute(query)
self.connection.commit()
def get_all_bookmarks(self):
"""
Returns all bookmarks in the database as a list.
"""
query = "SELECT * FROM bookmarks"
self.cursor.execute(query)
return self.cursor.fetchall()
def get_bookmark(self, bookmark_id):
"""
With the provided `bookmark_id`, the database will be
searched for a matching entry, with the row returned
if there is a match. If there is no match, None will
be returned.
`bookmark_id` is of type uuid.UUID()
"""
query = "SELECT * FROM bookmarks WHERE bookmark_id = ?"
self.cursor.execute(query, (bookmark_id, ))
return self.cursor.fetchone()
def save_bookmark(self, uri, title):
"""
Determines if the provided `uri` doesn't already
exist in the database adding a new entry if that
is the case. If the `uri` is already stored
(based on the generated UUID), the existing
entry's UUID will be returned instead.
"""
uri_uuid = uuid.uuid5(uuid.NAMESPACE_URL, uri)
bookmark_exists = self.get_bookmark(uri_uuid)
if bookmark_exists != None:
return bookmark_exists[0]
query = """
INSERT INTO bookmarks (
bookmark_id, uri, title, create_date
) VALUES (?, ?, ?, ?)
"""
self.cursor.execute(query, (uri_uuid, uri, title, datetime.datetime.now()))
self.connection.commit()
return uri_uuid
def delete_bookmark(self, bookmark_id):
"""
Removes the bookmark entry if it exists
`bookmark_id` is of type uuid.UUID()
Returns True upon successful removal.
Returns False upon unsuccessful removal.
"""
if self.get_bookmark(bookmark_id) != None:
query = "DELETE FROM bookmarks WHERE bookmark_id = ?"
self.cursor.execute(query, (bookmark_id, ))
self.connection.commit()
if self.get_bookmark(bookmark_id) == None:
return True
return False
def update_bookmark_title(self, bookmark_id, new_title):
"""
Takes the provided `bookmark_id`, searches the
database for the matching record, and if found
the title will be replaced with `new_title`.
`bookmark_id` is of type uuid.UUID()
Returns None if there is no matching bookmark.
"""
bookmark = self.get_bookmark(bookmark_id)
if bookmark != None:
query = """
UPDATE bookmarks
SET title = ?, update_date = ?
WHERE bookmark_id = ?
"""
self.cursor.execute(query, (new_title, datetime.datetime.now(), bookmark_id, ))
self.connection.commit()
return self.get_bookmark(bookmark_id)
return None
def update_bookmark_uri(self, bookmark_id, new_uri):
"""
Takes the provided `bookmark_id`, searches the
database for the matching record, and if found
the URI will be replaced with `new_uri`.
`bookmark_id` is of type uuid.UUID()
A new `bookmark_id` will be generated if the
`new_uri` is different than what was previously
stored. If the newly generated `bookmark_id` matches
an existing entry, this method will return False.
You may want to delete the old bookmark in this case.
Returns None if there is no matching bookmark.
"""
bookmark = self.get_bookmark(bookmark_id)
if bookmark != None:
query = """
UPDATE bookmarks
SET bookmark_id = ?, uri = ?, update_date = ?
WHERE bookmark_id = ?
"""
new_bookmark_id = uuid.uuid5(uuid.NAMESPACE_URL, new_uri)
if self.get_bookmark(new_bookmark_id) == None:
self.cursor.execute(query, (new_bookmark_id, new_uri, datetime.datetime.now(), bookmark_id, ))
self.connection.commit()
return self.get_bookmark(new_bookmark_id)
return False
return None

63
api/db/telethon_db.py Normal file
View File

@ -0,0 +1,63 @@
#!/usr/bin/env python3
# Copyright 2020 - David Todd (c0de@c0defox.es)
# Licensed under the MIT License (https://opensource.org/licenses/MIT)
"""
This file contains the database for authorizing users
of the simple bookmark application
"""
import datetime
import sqlite3
import uuid
class TelethonDatabase(Database):
"""
This class contains various methods for interacting
with the database for the Telethon Authenticator
"""
def __init__(self, database):
"""
Sets up the database connection + cursor
as well as creates a new table if it doesn't
exist in the database that is provided via the
instantiation of this class
"""
super(TelethonDatabase, self).__init__(database)
# Automatically create the table if it doesn't
# already exist in the selected database
self._create_table()
def _create_table(self):
"""
Creates a table called `telethon`
that uses UUID as the primary key.
The UUID is a randomly generated UUID4
`client_ip` is the IP address that the server
recognized when the request was made
`auth_key` is the key that the user will use when
making API requests
`active` is a boolean value for whether or not to
authorize uses of `auth_key`
`create_date` and `update_date` are the datetimes
that the entry was created and updated, respectively.
"""
query = """
CREATE TABLE IF NOT EXISTS telethon (
uuid GUID PRIMARY KEY,
client_ip TEXT NOT NULL,
auth_key TEXT NOT NULL,
active BOOLEAN NOT NULL,
create_date TIMESTAMP NOT NULL,
update_date TIMESTAMP
)
"""
self.cursor.execute(query)
self.connection.commit()