From 290e72f15938009aaed1d5d47f52a87ee7478cc4 Mon Sep 17 00:00:00 2001 From: Darksider3 Date: Sun, 13 Oct 2019 19:20:25 +0200 Subject: [PATCH] Add various documentation to the System class and sqlitedb-Class... ... which are all written in rst-format, which sphynx understands and has an own formal specification in http://docutils.sourceforge.net/rst.html --- private/ListUsers.py | 8 +++- private/lib/System.py | 81 ++++++++++++++++++++++++++++++++++++++--- private/lib/sqlitedb.py | 40 ++++++++++++++++++++ 3 files changed, 122 insertions(+), 7 deletions(-) diff --git a/private/ListUsers.py b/private/ListUsers.py index 6deb520..428d54a 100644 --- a/private/ListUsers.py +++ b/private/ListUsers.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -import sqlite3 from lib.sqlitedb import SQLitedb import lib.CFG as CFG @@ -22,7 +21,12 @@ class ListUsers: def prettyPrint(self) -> None: pass # see below why not implemented yet, texttable... - def getFetch(self) -> sqlite3: + def getFetch(self) -> list: + """ Returns a complete fetch done by the sqlitedb-class + + :return: Complete fetchall() in a dict-factory + :rtype: list + """ return self.usersFetch diff --git a/private/lib/System.py b/private/lib/System.py index 354a4ff..a32f281 100644 --- a/private/lib/System.py +++ b/private/lib/System.py @@ -5,15 +5,34 @@ import pwd class System: + """Class to interact with the system specifically to support our needs 0w0""" dry = False create_command = [] home = "" def __init__(self, dryrun: bool = False, home: str = "/home/"): + """Creates an objects. Can set dry run. + + :param dryrun: Run all command in a dry-run? When enabled, doesn't make any changes to the system (defaults to + false) + :type dryrun: bool + :param home: Standard directory to search for the home directories of your users(default is /home/) + :type home: str + """ self.dry = dryrun self.home = home - def register(self, username: str, pubkey: str, cc: tuple = tuple(["useradd", "-m"])) -> bool: + def register(self, username: str, cc: tuple = tuple(["useradd", "-m"])) -> bool: + """Creates an local account for the given username + + :param username: Username to create + :type username: str + :param cc: Tuple with commands separated to execute on the machine. (defaults to useradd -m) + :type cc: tuple + :returns: True, when the user was successfully created, False when not + :rtype: bool + """ + create_command = cc cc = create_command + tuple([username]) if self.dry: @@ -32,16 +51,28 @@ class System: # @TODO errno def make_ssh_usable(self, username: str, pubkey: str, sshdir: str = ".ssh/") -> bool: + """ Make SSH usable for our newly registered user + + :param username: Username you want to affect with it, casually used directly after register() + :type username: str + :param pubkey: Public SSH Key for the User you want accessible by SSH + :type pubkey: str + :param sshdir: Directory to write the authorized_keys File to. PWD is $HOME of said user. (defaults to ".ssh/") + :type sshdir: str + :return: True, when everything worked out good, false when something bad happened. Outputs the error of it. + :rtype: bool + """ + if self.dry: print("Nah, @TODO, but actually kinda too lazy for this lul. Just a lot happening here") return True if not sshdir.endswith("/"): - return False # @TODO Exception in Log + return False # @TODO Exception in Log ssh_dir = self.home + username + "/" + sshdir try: os.mkdir(ssh_dir) except FileExistsError: - pass # thats actually a good one for us :D + pass # thats actually a good one for us :D except OSError as e: print(f"Could not create {ssh_dir}: Exception: {e}", file=sys.stderr) return False @@ -57,7 +88,7 @@ class System: return False # @TODO Exception in Log try: pwdnam = pwd.getpwnam(username) - os.chown(ssh_dir, pwdnam[2], pwdnam[3]) # 2=>uid, 3=>gid + os.chown(ssh_dir, pwdnam[2], pwdnam[3]) # 2=>uid, 3=>gid os.chown(ssh_dir + "authorized_keys", pwd.getpwnam(username)[2], pwd.getpwnam(username)[3]) except OSError as e: print(f"Could not chown {ssh_dir} and/or authorized_keys to {username} and their group, Exception: {e}", @@ -66,6 +97,16 @@ class System: return True def lock_user_pw(self, username: str, cc: tuple = tuple(["usermod", "--lock"])) -> bool: + """Lock a users password so it stays empty + + :param username: Username of the user which accounts password you want to lock + :type username: str + :param cc: Commands to run in the subprocess to lock it down(defaults to usermod --lock) + :type cc: tuple + :rtype: bool + :return: True when the lock worked, false when not. + """ + lock_command = cc cc = lock_command + tuple([username]) if self.dry: @@ -80,6 +121,18 @@ class System: return True def add_to_usergroup(self, username: str, group: str = "tilde", cc: tuple = tuple(["usermod", "-a", "-G"])) -> bool: + """ Adds a given user to a given group + + :param username: Username to add to your wanted group + :type username: str + :param group: Groupname where you want to add your user to + :type group: str + :param cc: Commands to execute that adds your user to said specific group(defaults to usermod -a -G") + :type cc: tuple + :return: True, if worked, False when not. + :rtype bool + """ + add_command = cc cc = add_command + tuple([group, username]) if self.dry: @@ -94,12 +147,30 @@ class System: return True def printTuple(self, tup: tuple) -> None: + """Prints a tuple with spaces as separators + + :param tup: Tuple you want to print + :type tup: tuple + :rtype: None + :returns: Nothing + """ + pp = "" for i in tup: pp += i + " " print(pp) def removeUser(self, username: str, cc: tuple = tuple(["userdel", "-r"])) -> bool: + """Removes the specified user from the system + + :param username: The username you want to delete from the system. + :type username: str + :param cc: Commands to execute to delete the user from the System(defaults to userdel -r) + :type cc: tuple + :return: True, when worked, False if not. + :rtype: bool + """ + remove_command = cc cc = remove_command + tuple([username]) if self.dry: @@ -116,7 +187,7 @@ class System: if __name__ == "__main__": try: S = System(dryrun=True) - S.register("dar", "test") + S.register("dar") S.lock_user_pw("dar") S.add_to_usergroup("dar") #if not S.make_ssh_usable("dar", "SSHpub"): diff --git a/private/lib/sqlitedb.py b/private/lib/sqlitedb.py index fed0953..d457cf9 100644 --- a/private/lib/sqlitedb.py +++ b/private/lib/sqlitedb.py @@ -12,12 +12,21 @@ def dict_factory(cursor, row): class SQLitedb: + """SQLitedb handles EVERYTHING directly related to our Database.""" + db = "" cursor = None connection = None last_result = None def __init__(self, dbpath: str): + """ + :param dbpath: Path to the database we want to open + :type dbpath: str + :returns: Object for the SQLitedb-Class. + :rtype: object + """ + db = dbpath try: self.connection = sqlite3.connect(db) @@ -35,6 +44,13 @@ class SQLitedb: print("Couldn't gracefully close db: %s" % e, file=STDERR) def query(self, qq: str) -> list: + """Do a query and automagically get the fetched results in a list + :param qq: Query to execute + :type qq: str + :returns: A tuple(/list) consisting with any fetched results + :rtype: list + """ + try: self.cursor.execute(qq) self.last_result = self.cursor.fetchall() @@ -46,11 +62,21 @@ class SQLitedb: # sometimes we need the cursor for safety reasons, for example does sqlite3 all the security related # escaoing in supplied strings for us, when we deliver it to con.execute in the second argument as a tuple def getCursor(self) -> sqlite3: + """Returns SQLite3 Cursor. Use with **c a u t i o n**... """ return self.cursor # we could try to utilise that ourselfs in a function. Be c a r e f u l, these values in the tuple MUST HAVE # THE RIGHT TYPE def safequery(self, qq: str, deliver: tuple) -> list: + """ Shall handle any query that has user input in it as an alternative to self.query + :param qq: Query to execute + :type qq: str + :param deliver: User inputs marked with the placeholder(`?`) in the str + :type deliver: tuple + :returns: A tuple(/list) consisting with any fetched results + :rtype: list + """ + try: self.cursor.execute(qq, deliver) self.last_result = self.cursor.fetchall() @@ -63,6 +89,13 @@ class SQLitedb: return self.last_result def removeApplicantFromDB(self, userid: int) -> bool: + """Removes Applicants from the DB by ID. Use along System.removeUser() + :param userid: User ID to remove from the Database + :type userid: int + :returns: True, if removal was successful(from the DB), False when not + :rtype: bool + """ + try: self.last_result = self.cursor.execute("DELETE FROM `applications` WHERE id = ? ", [userid]) self.connection.commit() @@ -72,6 +105,13 @@ class SQLitedb: return True def removeApplicantFromDBperUsername(self, username: str) -> bool: + """Removes Applicants from the DB by Username. Use along System.removeUser() + :param username: Username to remove from the database + :type username: str + :returns: True, if removal was successful(from the DB), False when not + :rtype: bool + """ + try: self.last_result = self.cursor.execute("DELETE FROM `applications` WHERE username = ?", [username]) self.connection.commit()