Merge remote-tracking branch 'origin/pr/3'

feature-admin-split
n1trux 5 years ago
commit 43a3dd81ac

@ -38,12 +38,10 @@ RUN mkdir -p /var/run/sshd
# expose SSH port # expose SSH port
EXPOSE 22 EXPOSE 22
ENV TILDE_CONF="/app/data/applicationsconfig.ini" ENV TILDE_CONF="/app/data/applicationsconfig.ini"
#COPY config/environment /app/user/.ssh/environment
RUN mkdir /app/user/.ssh
RUN echo TILDE_CONF=$TILDE_CONF > /app/user/.ssh/environment
RUN touch /app/data/applications.sqlite RUN touch /app/data/applications.sqlite
RUN touch /app/data/applications.log RUN touch /app/data/applications.log
# Doesnt work, @TODO why # Doesnt work, @TODO why
#RUN setfacl -R -m u:tilde:rwx /app/data/ #RUN setfacl -R -m u:tilde:rwx /app/data/
RUN chown -R tilde /app/data RUN chown -R tilde /app/data
CMD ["/usr/sbin/sshd", "-D"] RUN mkdir /app/user/.ssh
CMD ["sh", "-c", " echo TILDE_CONF=$TILDE_CONF > /app/user/.ssh/environment && /usr/sbin/sshd -D"]

@ -4,388 +4,395 @@ import configparser, logging, sqlite3, argparse, pwd
import os import os
import subprocess import subprocess
# Clear shell # Clear shell
def clear(): def clear():
os.system('cls' if os.name == 'nt' else 'clear') os.system('cls' if os.name == 'nt' else 'clear')
# create dictionary out of sqlite results # create dictionary out of sqlite results
def dict_factory(cursor, row): def dict_factory(cursor, row):
d = {} d = {}
for idx, col in enumerate(cursor.description): for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx] d[col[0]] = row[idx]
return d return d
# prints command(but doesnt execute them) # prints command(but doesnt execute them)
# need this for work, just convenience # need this for work, just convenience
def debugExec(commands): def debugExec(commands):
print("Commands: {!s} -> Returns 0".format(commands)) print("Commands: {!s} -> Returns 0".format(commands))
return 0 return 0
# @TODO hardcoded config? # @TODO hardcoded config?
cwd = os.environ.get('TILDE_CONF') cwd = os.environ.get('TILDE_CONF')
if cwd is None: if cwd is None:
cwd=os.getcwd()+"/applicationsconfig.ini" cwd = os.getcwd() + "/applicationsconfig.ini"
else: else:
if os.path.isfile(cwd) is False: if os.path.isfile(cwd) is False:
cwd=os.getcwd()+"/applicationsconfig.ini" cwd = os.getcwd() + "/applicationsconfig.ini"
# cwd is now either cwd/applicationsconfig or $TILDE_CONF # cwd is now either cwd/applicationsconfig or $TILDE_CONF
argparser = argparse.ArgumentParser(description = 'interactive registration formular for tilde platforms') argparser = argparse.ArgumentParser(description='interactive registration formular for tilde platforms')
argparser.add_argument('-c', '--config', default = cwd, argparser.add_argument('-c', '--config', default=cwd,
type = str, help = 'Path to configuration file', required = False) type=str, help='Path to configuration file', required=False)
args = argparser.parse_args() args = argparser.parse_args()
CONF_FILE = args.config CONF_FILE = args.config
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read(CONF_FILE) config.read(CONF_FILE)
logging.basicConfig(format="%(asctime)s: %(message)s", logging.basicConfig(format="%(asctime)s: %(message)s",
level = int(config['LOG_LEVEL']['log_level']) level=int(config['LOG_LEVEL']['log_level'])
) )
del(cwd) del cwd
REG_FILE = config['DEFAULT']['applications_db'] REG_FILE = config['DEFAULT']['applications_db']
# Does everything related to applicants, i.e. creating, manipulations... # Does everything related to applicants, i.e. creating, manipulations...
class applicants(): class Applicants:
# User identifier # User identifier
identifier = "username" identifier = "username"
# SQLite DB Path # SQLite DB Path
sourceDB = "" sourceDB = ""
# another sqlite to batch-recreate users # another sqlite to batch-recreate users
differentDB = "" differentDB = ""
def __init__(self, lident, sourceDB=REG_FILE):
self.identifier = lident def __init__(self, lident, sourcedb=REG_FILE):
self.sourceDB = sourceDB self.identifier = lident
self.__connectToDB__("source") self.sourceDB = sourcedb
# all results shall be done with dict_factory! Makes everything so much simpler self.__connectToDB__("source")
self.sdbCursor.row_factory = dict_factory # all results shall be done with dict_factory! Makes everything so much simpler
self.sdbCursor.row_factory = dict_factory
def __del__(self):
self.__closeDB__("source") def __del__(self):
self.__closeDB__("source")
def __connectToDB__(self, which):
if which == "source": def __connectToDB__(self, which):
try: if which == "source":
self.sdbConnection = sqlite3.connect(self.sourceDB) try:
self.sdbCursor = self.sdbConnection.cursor() self.sdbConnection = sqlite3.connect(self.sourceDB)
except sqlite3.Error as e: self.sdbCursor = self.sdbConnection.cursor()
logging.exception("Database: Couldn't open database and get cursor: %s" % e) except sqlite3.Error as e:
else: logging.exception("Database: Couldn't open database and get cursor: %s" % e)
self.ddbConnection = sqlite3.connect(self.differentDB) else:
self.ddbCursor = self.ddbConnection.cursor() self.ddbConnection = sqlite3.connect(self.differentDB)
self.ddbCursor = self.ddbConnection.cursor()
def __closeDB__(self, which):
if(which == "source"): def __closeDB__(self, which):
try: if which == "source":
self.sdbConnection.close() try:
except sqlite3.Error as e: self.sdbConnection.close()
logging.exception("Couldn't close database! Error: %s" % e) # @TODO: Dump full db with query or just the executed querys to file except sqlite3.Error as e:
else: logging.exception(
self.ddbConnection.close() # @TODO: Evaluate getting rid of ddb(differentDB)? "Couldn't close database! Error: %s" % e)
# @TODO: Dump full db with query or just the executed querys to file
# get List of all applications(not accepted yet) else:
def getApplicationsList(self): self.ddbConnection.close() # @TODO: Evaluate getting rid of ddb(differentDB)?
query = "SELECT * FROM `applications` WHERE `status` = '0'"
try: # get List of all applications(not accepted yet)
self.sdbCursor.execute(query) def getapplicationslist(self):
rows = self.sdbCursor.fetchall() query = "SELECT * FROM `applications` WHERE `status` = '0'"
except sqlite3.Error as e: try:
logging.exception("Database Error: %s" % e) self.sdbCursor.execute(query)
rows=[] rows = self.sdbCursor.fetchall()
return rows except sqlite3.Error as e:
logging.exception("Database Error: %s" % e)
def getApprovedApplicantsList(self): rows = []
query = "SELECT * From `applications` WHERE `status` = '1'" return rows
try:
self.sdbCursor.execute(query) def getapprovedapplicantslist(self):
rows = self.sdbCursor.fetchall() query = "SELECT * From `applications` WHERE `status` = '1'"
except sqlite3.Error as e: try:
logging.exception("Database Error: %s" % e) self.sdbCursor.execute(query)
rows=[] rows = self.sdbCursor.fetchall()
return rows except sqlite3.Error as e:
logging.exception("Database Error: %s" % e)
# edit aproved users rows = []
def editApprovedApplicant(self, term, updaterow): return rows
try:
self.sdbCursor.execute( # edit aproved users
"UPDATE `applications` SET ? WHERE id=?", def editapprovedapplicants(self, term):
( str(term), ) try:
) # the fuck did i try here?
self.sdbConnection.commit() self.sdbCursor.execute(
except sqlite3.Error as e: "UPDATE `applications` WHERE id=?", (str(term),)
logging.exception("Database Error: %s" % e) )
self.sdbConnection.commit()
# set user to aproved except sqlite3.Error as e:
def setApprovedApplication(self, selectterm): logging.exception("Database Error: %s" % e)
query = "SELECT `username` FROM `applications` WHERE `username` = `{0!s}`".format(selectterm)
# set user to aproved
# get applicants data def setapprovedapplication(self, selectterm):
def getApplicantsData(self, term): # query = "SELECT `username` FROM `applications` WHERE `username` = `{0!s}`".format(selectterm)
# @TODO: Use shorthand if for the correct query, directly into sqlite pass
if self.identifier == "id":
try: # get applicants data
self.sdbCursor.execute( def getapplicantsdata(self, term):
"SELECT * FROM `applications` WHERE id = ?", # @TODO: Use shorthand if for the correct query, directly into sqlite
( str(term), ) if self.identifier == "id":
) try:
except sqlite3.Error as e: self.sdbCursor.execute(
logging.exception("Database Error: %s" % e) "SELECT * FROM `applications` WHERE id = ?",
(str(term),)
else: )
self.sdbCursor.execute( except sqlite3.Error as e:
"SELECT * FROM `applications` WHERE username = ?", logging.exception("Database Error: %s" % e)
( str(term), )
) else:
result = self.sdbCursor.fetchone() self.sdbCursor.execute(
return result "SELECT * FROM `applications` WHERE username = ?",
(str(term),)
# @TODO: migrade just approved users to some new/another sqlitedb )
def migrateApprovedData(self, different_db): result = self.sdbCursor.fetchone()
pass return result
# @TODO: delete migrated data # @TODO: migrade just approved users to some new/another sqlitedb
def deleteMigratedDataSet(self, selectterm): def migrateapproveddata(self, different_db):
pass pass
# Applicants whom doesnt got approved should get removed # @TODO: delete migrated data
def removeApplicant(self, term): def deletemigrateddata(self, selectterm):
if self.identifier == "id": pass
try:
self.sdbCursor.execute( # Applicants whom doesnt got approved should get removed
"DELETE FROM `applications` WHERE id = ?", def removeapplicant(self, term):
( str(term), ) if self.identifier == "id":
) try:
self.sdbConnection.commit() self.sdbCursor.execute(
except sqlite3.Error as e: "DELETE FROM `applications` WHERE id = ?",
logging.exception("Database Error: %s" % e) (str(term),)
)
else: self.sdbConnection.commit()
self.sdbCursor.execute( except sqlite3.Error as e:
"DELETE FROM `applications` WHERE username = ?", logging.exception("Database Error: %s" % e)
( str(term), )
) else:
self.sdbConnection.commit() self.sdbCursor.execute(
'DELETE FROM `applications` WHERE username = ?',
#@TODO: Possibility to work without passing users manually (str(term),)
def selectedUser(userid, username = False): )
pass self.sdbConnection.commit()
# Print out a list of aprovable users # @TODO: Possibility to work without passing users manually
def printApprovableUsers(self, users): def selecteduser(userid, username=False):
i=0 pass
for user in users:
print("ID: {0!s}, Status: {0!s}, Name: {0!s}".format(i, user["status"], user["username"])) # Print out a list of aprovable users
i += 1 def printapprovableusers(self, users):
return i i = 0
for user in users:
# Get List of users print("ID: {0!s}, Status: {0!s}, Name: {0!s}".format(i, user["status"], user["username"]))
def userPrint(self, fetched, userid): i += 1
print("ID: {0!s}".format(fetched[int(userid)]["id"])) return i
print("Username: {0!s}".format(fetched[int(userid)]["username"]))
print("Mail: {0!s}".format(fetched[int(userid)]["email"])) # Get List of users
print("SSH: {0!s}".format(fetched[int(userid)]["pubkey"])) @staticmethod
print("Registrated time: {0!s}".format(fetched[int(userid)]["timestamp"])) def userprint(fetched, userid):
print("ID: {0!s}".format(fetched[int(userid)]["id"]))
# Approve an applicant. Handles everything related, like create home dir, set flags blabla print("Username: {0!s}".format(fetched[int(userid)]["username"]))
def approveApplicant(self, term): print("Mail: {0!s}".format(fetched[int(userid)]["email"]))
user = self.getApplicantsData(term) print("SSH: {0!s}".format(fetched[int(userid)]["pubkey"]))
ret = self.__execScript(user) print("Registrated time: {0!s}".format(fetched[int(userid)]["timestamp"]))
if ret[0] != 0: # @DEBUG: Change to == 0
print("Something went wrong in the user creation! Exiting without deleting users record in database!") # Approve an applicant. Handles everything related, like create home dir, set flags blabla
print("Last executed commands: {0!s}\nreturn code: {1!s}".format(ret[-1][1], ret[-1][0])) def approveapplicant(self, term):
exit(0) user = self.getapplicantsdata(term)
ret = self.__execScript(user)
if self.identifier == "id": if ret[0] != 0: # @DEBUG: Change to == 0
try: print("Something went wrong in the user creation! Exiting without deleting users record in database!")
self.sdbCursor.execute( print("Last executed commands: {0!s}\nreturn code: {1!s}".format(ret[-1][1], ret[-1][0]))
"UPDATE `applications` SET `status`=1 WHERE `id`=?", exit(0)
( str(term), )
) if self.identifier == "id":
self.sdbConnection.commit() try:
except sqlite3.Error as e: self.sdbCursor.execute(
logging.exception("Database Error: %s" % e) "UPDATE `applications` SET `status`=1 WHERE `id`=?",
(str(term),)
else: )
self.sdbCursor.execute( self.sdbConnection.commit()
"UPDATE `applications` SET `status`=1 WHERE `username`=?" except sqlite3.Error as e:
( str(term), ) logging.exception("Database Error: %s" % e)
)
self.sdbConnection.commit() else:
self.sdbCursor.execute(
# Script execution, handles everything done with the shell/commands themselves "UPDATE `applications` SET `status`=1 WHERE `username`=?",
def __execScript(self, user): (str(term), )
# @TODO: omfg just write some wrapper-class/lib... sucks hard! )
username=user["username"] self.sdbConnection.commit()
homeDir="/home/"+username+"/"
sshDir=homeDir+".ssh/" # Script execution, handles everything done with the shell/commands themselves
executed=[] @staticmethod
def __execScript(user):
executed.append(["useradd", "-m", username]) # @TODO: omfg just write some wrapper-class/lib... sucks hard!
rcode = subprocess.call(executed[0]) username = user["username"]
if rcode != 0: home_dir = "/home/" + username + "/"
return [rcode,executed,] ssh_dir = home_dir + ".ssh/"
executed = []
executed.append(["usermod", "--lock", username])
rcode = subprocess.call(executed[1]) #empty pw executed.append(["useradd", "-m", username])
if rcode != 0: returncode = subprocess.call(executed[0])
return [rcode,executed,] if returncode != 0:
return [returncode, executed, ]
executed.append(["usermod", "-a", "-G", "tilde", username])
rcode = subprocess.call(executed[2]) # add to usergroup executed.append(["usermod", "--lock", username])
if rcode != 0: returncode = subprocess.call(executed[1]) # empty pw
return [rcode,executed,] if returncode != 0:
return [returncode, executed, ]
executed.append(["mkdir", sshDir])
try: executed.append(["usermod", "-a", "-G", "tilde", username])
# @TODO: use config variable(chmodPerms) returncode = subprocess.call(executed[2]) # add to usergroup
ret = os.mkdir(sshDir, 0o777) #create sshdir if returncode != 0:
rcode = 0 return [returncode, executed, ]
except OSError as e:
logging.exception(e.strerror) executed.append(["mkdir", ssh_dir])
rcode = e.errno # False, couldn't create. try:
return [rcode,executed,] # @TODO: use config variable(chmodPerms)
os.mkdir(ssh_dir, 0o777) # create sshdir
executed.append(["write(sshkey) to", sshDir+"authorized_keys"]) returncode = 0
with open(sshDir+"authorized_keys", "w") as f: except OSError as e:
f.write(user["pubkey"]) logging.exception(e.strerror)
if f.closed != True: returncode = e.errno # False, couldn't create.
logging.exception("Could'nt write to authorized_keys!") return [returncode, executed, ]
return [rcode,executed,]
executed.append(["write(sshkey) to", ssh_dir + "authorized_keys"])
executed.append(["chmod", "-Rv", "700", sshDir]) with open(ssh_dir + "authorized_keys", "w") as f:
f.write(user["pubkey"])
if not f.closed:
logging.exception("Could'nt write to authorized_keys!")
return [returncode, executed, ]
executed.append(["chmod", "-Rv", "700", ssh_dir])
try:
os.chmod(ssh_dir + "authorized_keys", 0o700) # directory is already 700
returncode = 0
except OSError as e:
logging.exception(e.strerror)
returncode = e.errno
return [returncode, executed, ]
try:
executed.append(["chown", "-Rv", username + ":" + username, ssh_dir])
os.chown(ssh_dir, pwd.getpwnam(username)[2], pwd.getpwnam(username)[3]) # 2=>uid, 3=>gid
executed.append(["chown", "-v", username + ":" + username, ssh_dir + "authorized_keys"])
os.chown(ssh_dir + "authorized_keys", pwd.getpwnam(username)[2], pwd.getpwnam(username)[3])
returncode = 0
except OSError as e:
logging.exception(e.strerror) # @TODO: maybe append strerror to executed instead of printing it
returncode = e.errno
return [returncode, executed, ]
return [returncode, executed, ]
# {'id': 7, 'username': 'testuser47', 'email': '47test@testmail.com', 'name':
# 'test Name', 'pubkey': 'ssh-rsa [...]', 'timestamp': '2018-08-22 13:31:16', 'status': 0}
try:
os.chmod(sshDir+"authorized_keys", 0o700) # directory is already 700
rcode = 0
except OSError as e:
logging.exception(e.strerror)
rcode = e.errno
return [rcode, executed,]
try:
executed.append(["chown", "-Rv", username+":"+username, sshDir])
os.chown(sshDir, pwd.getpwnam(username)[2], pwd.getpwnam(username)[3]) #2=>uid, 3=>gid
executed.append(["chown", "-v", username+":"+username, sshDir+"authorized_keys"])
os.chown(sshDir+"authorized_keys", pwd.getpwnam(username)[2], pwd.getpwnam(username)[3])
rcode = 0
except OSError as e:
logging.exception(e.strerror) # @TODO: maybe append strerror to executed instead of printing it
rcode = e.errno
return [rcode, executed,]
return [rcode,executed,]
"""
{'id': 7, 'username': 'testuser47', 'email': '47test@testmail.com', 'name':
'test Name', 'pubkey': 'ssh-rsa [...]', 'timestamp': '2018-08-22 13:31:16', 'status': 0}
"""
def main(): def main():
# how many times the Seperator/Delimiter? # how many times the Separator/Delimiter?
delcount = 40 delcount = 40
# The seperator for the menu # The separator for the menu
Seperator = "="*delcount separator = "=" * delcount
Menu = Seperator+"\n\t\t Main-Menu:\n\n" \ menu = separator + "\n\t\t Main-Menu:\n\n" \
"\t 1) list and edit pending users\n"\ "\t 1) list and edit pending users\n" \
"\t 2) list applicants\n"\ "\t 2) list applicants\n" \
"\t 3) edit applicant\n"\ "\t 3) edit applicant\n" \
"\t 4) quit\n"+Seperator+"\n" "\t 4) quit\n" + separator + "\n"
# Identify by ID # Identify by ID
applications = applicants(lident = "id") applications = Applicants(lident="id")
while 1 != 0: while 1 != 0:
print(Menu) print(menu)
command = input("Please select, what you want to do: \n -> ") command = input("Please select, what you want to do: \n -> ")
# User shouldnt be able to type something in that isnt a number # User shouldn't be able to type something in that isnt a number
if command.isalpha() or command == '': if command.isalpha() or command == '':
clear()
print("!!! invalid input, please try again. !!!")
continue
# convert
command=int(command)
if command == 4 or command == "q":
exit(0)
# Edit and list pending users/applicants @TODO Wording: Users or applicants?
elif command == 1:
users = applications.getApplicationsList()
i=applications.printApprovableUsers(users)
if i == 0 :
print("No pending users")
# giving some time to aknowledge that something WRONG happened
input("Continue with Keypress...")
clear()
continue
usersel = 0
UserMax = i
print("Menu:\n r=>return to main")
# Edit Menue
while 1 != 0 or usersel != "r":
i = applications.printApprovableUsers(users)
if usersel == "r":
break # break when user presses r
usersel = input("Which user( ID ) do you want to change? ->")
if len(usersel) > 1 or usersel.isalpha():
usersel = ""
# convert to int if input isnt an r
usersel = int(usersel) if usersel != '' and usersel != 'r' else 0
if usersel > UserMax - 1:
print("User {0!s} doesn't exist!".format(usersel))
continue
# Show the user his chosen user and ask what to do
applications.userPrint(users, usersel)
print("You chosed ID No. {0!s}, what do you like to do?".format(usersel))
chosenUser = usersel
usersel = ""
# Finally down the edit menue!
while usersel != "e":
usersel = input("User: {0!s}\n \t\t(A)ctivate \n\t\t(R)emove \n\t\tR(e)turn\n -> ".format(chosenUser))
if usersel == "A":
applications.approveApplicant(users[chosenUser]['id'])
print("User {0!s} has been successfully approved!".format(users[chosenUser]['username']))
input("waiting for input...")
clear()
usersel="e" # remove for being able to continue editing?
continue
elif usersel == "R":
applications.removeApplicant(users[chosenUser]['id'])
print("User {0!s} successfully deleted!".format(user[chosenUser]['username']))
input("waiting for input...")
clear() clear()
print("!!! invalid input, please try again. !!!")
continue continue
elif usersel == "e":
clear() # convert
command = int(command)
if command == 4 or command == "q":
exit(0)
# Edit and list pending users/applicants @TODO Wording: Users or applicants?
elif command == 1:
users = applications.getapplicationslist()
i = applications.printapprovableusers(users)
if i == 0:
print("No pending users")
# giving some time to acknowledge that something WRONG happened
input("Continue with Keypress...")
clear()
continue
user_selection = 0
user_max = i
print("Menu:\n r=>return to main")
# Edit Menu
while 1 != 0 or user_selection != "r":
i = applications.printapprovableusers(users)
if user_selection == "r":
break # break when user presses r
user_selection = input("Which user( ID ) do you want to change? ->")
if len(user_selection) > 1 or user_selection.isalpha():
user_selection = ""
# convert to int if input isnt an r
user_selection = int(user_selection) if user_selection != '' and user_selection != 'r' else 0
if user_selection > user_max - 1:
print("User {0!s} doesn't exist!".format(user_selection))
continue
# Show the user his chosen user and ask what to do
applications.userprint(users, user_selection)
print("You chosed ID No. {0!s}, what do you like to do?".format(user_selection))
chosen_user = user_selection
user_selection = ""
# Finally down the edit menu!
while user_selection != "e":
user_selection = input(
"User: {0!s}\n \t\t(A)ctivate \n\t\t(R)emove \n\t\tR(e)turn\n -> ".format(chosen_user))
if user_selection == "A":
applications.approveapplicant(users[chosen_user]['id'])
print("User {0!s} has been successfully approved!".format(users[chosen_user]['username']))
input("waiting for input...")
clear()
user_selection = "e" # remove for being able to continue editing?
continue
elif user_selection == "R":
applications.removeapplicant(users[chosen_user]['id'])
print("User {0!s} successfully deleted!".format(user[chosen_user]['username']))
input("waiting for input...")
clear()
continue
elif user_selection == "e":
clear()
continue
elif int(command) == 2:
users = applications.getapprovedapplicantslist()
if not users:
print("no activate users yet!")
i = 0
for user in users:
print("ID: {0!s}, Status: {1!s}, Name: {2!s}".format(user["id"], user["status"], user["username"]))
continue continue
elif command == str(3):
elif int(command) == 2: pass
users = applications.getApprovedApplicantsList() else:
exit(0)
if users == []:
print("no activate users yet!")
i=0
for user in users:
print("ID: {0!s}, Status: {1!s}, Name: {2!s}".format(user["id"], user["status"], user["username"]))
continue
elif command == str(3):
pass
else:
exit(0)
if __name__ == "__main__": if __name__ == "__main__":
try: try:
main() main()
exit(0) exit(0)
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
#print("Exception occured. View log file for details.") # print("Exception occured. View log file for details.")
#logging.exception("Some exception occured") # logging.exception("Some exception occured")

@ -8,164 +8,171 @@ import re, configparser, logging, sqlite3
try: try:
cwd = environ.get('TILDE_CONF') cwd = environ.get('TILDE_CONF')
if cwd is None: if cwd is None:
cwd=getcwd()+"/applicationsconfig.ini" cwd=getcwd()+"/applicationsconfig.ini"
else: else:
if ospath.isfile(cwd) is False: if ospath.isfile(cwd) is False:
cwd=getcwd()+"/applicationsconfig.ini" cwd=getcwd()+"/applicationsconfig.ini"
# cwd is now either cwd/applicationsconfig or $TILDE_CONF # cwd is now either cwd/applicationsconfig or $TILDE_CONF
argparser = argparse.ArgumentParser(description='interactive registration formular for tilde platforms') argparser = argparse.ArgumentParser(description='interactive registration formular for tilde platforms')
argparser.add_argument('-c', '--config', default=cwd, type=str, help='Config file', required=False) argparser.add_argument('-c', '--config', default=cwd, type=str, help='Config file', required=False)
args = argparser.parse_args() args = argparser.parse_args()
CONF_FILE=args.config CONF_FILE = args.config
except: except:
logging.exception("Argumentparser-Exception: ") # intended broad, @TODO check them all for errors instead of everything in one
logging.exception("Argumentparser-Exception: ")
exit(0)
try: try:
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read(CONF_FILE) config.read(CONF_FILE)
logging.basicConfig(format="%(asctime)s: %(message)s", filename=config['DEFAULT']['log_file'],level=int(config['LOG_LEVEL']['log_level'])) logging.basicConfig(format="%(asctime)s: %(message)s", filename=config['DEFAULT']['log_file'],
del(cwd) level=int(config['LOG_LEVEL']['log_level']))
REG_FILE=config['DEFAULT']['applications_db'] REG_FILE = config['DEFAULT']['applications_db']
except: except:
logging.exception("logging or configparser-Exception: ") # intended broad, @TODO check them all for errors instead of everything in one
logging.exception("logging or configparser-Exception: ")
exit(0)
VALID_SSH=False VALID_SSH = False
VALID_USER=False VALID_USER = False
def __createTable(cursor, connection): def __createTable(cursor, connection):
try: try:
cursor.execute( cursor.execute(
"CREATE TABLE IF NOT EXISTS applications(" \ "CREATE TABLE IF NOT EXISTS applications("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"\ "id INTEGER PRIMARY KEY AUTOINCREMENT,"
"username TEXT NOT NULL, email TEXT NOT NULL,"\ "username TEXT NOT NULL, email TEXT NOT NULL,"
"name TEXT NOT NULL, pubkey TEXT NOT NULL,"\ "name TEXT NOT NULL, pubkey TEXT NOT NULL,"
"timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, status INTEGER NOT NULL DEFAULT 0);") "timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, status INTEGER NOT NULL DEFAULT 0);")
connection.commit() connection.commit()
except: except sqlite3.Error as e:
logging.exception("Couldn't create needed SQLite Table!") logging.exception("Couldn't create needed SQLite Table! Exception: %s" % e)
def addtotable(cursor, connection, username, name, email, pubkey): def addtotable(cursor, connection, username, name, email, pubkey):
try: try:
cursor.execute("INSERT INTO 'applications'(username, name, email, pubkey)VALUES("\ cursor.execute("INSERT INTO 'applications'(username, name, email, pubkey)VALUES("
"?,?,?,?)", [username, name, email, pubkey]) "?,?,?,?)", [username, name, email, pubkey])
connection.commit() connection.commit()
except: except sqlite3.Error as e:
logging.exception("Couldn't insert user into the db") logging.exception("Couldn't insert user into the db: %s" % e)
# check if sqlite file does exists or already and has our structure # check if sqlite file does exists or already and has our structure
def __checkSQLite(cursor, connection): def __checkSQLite(cursor, connection):
#SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}'; # SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='applications'") cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='applications'")
res=cursor.fetchall() res = cursor.fetchall()
if res== []: if not res:
try: try:
__createTable(cursor, connection) __createTable(cursor, connection)
except: except sqlite3.Error as e:
logging.exception("couldn't create table on given database. Exception: ") logging.exception("couldn't create table on given database. Exception: %s" % e)
else: else:
pass pass
return True return True
def check_username(value): def check_username(value):
global VALID_USER global VALID_USER
if len(value) < 3: if len(value) < 3:
VALID_USER=False VALID_USER=False
return False
try:
from pwd import getpwnam
getpwnam(value)
VALID_USER = False
# intended broad
except Exception:
VALID_USER = True
return True
return False return False
try:
from pwd import getpwnam
getpwnam(value)
VALID_USER=False
except:
VALID_USER=True
return True
return False
# taken from https://github.com/hashbang/provisor/blob/master/provisor/utils.py, all belongs to them! ;) # taken from https://github.com/hashbang/provisor/blob/master/provisor/utils.py, all belongs to them! ;)
def validate_pubkey(value): def validate_pubkey(value):
global VALID_SSH global VALID_SSH
import base64 import base64
if len(value) > 8192 or len(value) < 80: if len(value) > 8192 or len(value) < 80:
VALID_SSH=False VALID_SSH=False
return False return False
value = value.replace("\"", "").replace("'", "").replace("\\\"", "") value = value.replace("\"", "").replace("'", "").replace("\\\"", "")
value = value.split(' ') value = value.split(' ')
types = [ 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', types = [ 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384',
'ecdsa-sha2-nistp521', 'ssh-rsa', 'ssh-dss', 'ssh-ed25519' ] 'ecdsa-sha2-nistp521', 'ssh-rsa', 'ssh-dss', 'ssh-ed25519' ]
if value[0] not in types: if value[0] not in types:
VALID_SSH=False VALID_SSH=False
return False return False
try: try:
base64.decodebytes(bytes(value[1], "utf-8")) base64.decodebytes(bytes(value[1], "utf-8"))
except TypeError: except TypeError:
VALID_SSH=False VALID_SSH=False
return False return False
VALID_SSH=True
return True
VALID_SSH=True
return True
def main(): def main():
print(" ▗▀▖ \n▗▖▖ ▐ ▌ ▌▛▀▖\n▘▝▗▖▜▀ ▌ ▌▌ ▌\n ▝▘▐ ▝▀▘▘ ▘") print(" ▗▀▖ \n▗▖▖ ▐ ▌ ▌▛▀▖\n▘▝▗▖▜▀ ▌ ▌▌ ▌\n ▝▘▐ ▝▀▘▘ ▘")
username = input("Welcome to the ~.fun user application form!\n\nWhat is your desired username? [a-z0-9] allowed:\n") username = input("Welcome to the ~.fun user application form!\n\nWhat is your desired username? [a-z0-9] allowed:\n")
while (not re.match("[a-z]+[a-z0-9]", username)) or (not check_username(username)): while (not re.match("[a-z]+[a-z0-9]", username)) or (not check_username(username)):
username = input("Invalid Username, maybe it exists already?\nValid characters are only a-z and 0-9.\nMake sure your username starts with a character and not a number." \ username = input("Invalid Username, maybe it exists already?\nValid characters are only a-z and 0-9."
"\nWhat is your desired username? [a-z0-9] allowed:\n") "\nMake sure your username starts with a character and not a number."
"\nWhat is your desired username? [a-z0-9] allowed:\n")
fullname = input("\nPlease enter your full name:\n") fullname = input("\nPlease enter your full name:\n")
while not re.match("\w+\s*\w*", username): while not re.match("\w+\s*\w*", username):
fullname = input("\nThat is not your real name.\nPlease enter your full name:\n") fullname = input("\nThat is not your real name.\nPlease enter your full name:\n")
email = input("\nPlease enter your email address:\n")
email = input("\nPlease enter your email address:\n") while not re.match("(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email):
while not re.match("(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email): email = input("\nThat is not a valid mail address.\nPlease enter your email address:\n")
email = input("\nThat is not a valid mail address.\nPlease enter your email address:\n")
pubkey = input("\nPlease paste your ssh public key:\n")
while (not re.match("ssh-(\w)+\s(\w+)(\s*)([a-zA-Z0-9@]*)", pubkey)) or (not validate_pubkey(pubkey)):
pubkey = input("\nPlease paste your ssh public key:\n") pubkey = input("\nPlease enter a valid public key. You can show it with ssh-keygen -f .ssh/id_rsa -y on your "
while (not re.match("ssh-(\w)+\s(\w+)(\s*)([a-zA-Z0-9@]*)", pubkey)) or (not validate_pubkey(pubkey)): "local machine.\nPlease enter your pubkey:\n")
pubkey = input("\nPlease enter a valid public key. You can show it with ssh-keygen -f .ssh/id_rsa -y on your local machine.\nPlease enter your pubkey:\n") validate_pubkey(pubkey)
validate_pubkey(pubkey)
print("\nUsername: {0!s}".format(username))
print("Full Name: {0!s}".format(fullname))
print("\nUsername: {0!s}".format(username)) print("Email: {0!s}".format(email))
print("Full Name: {0!s}".format(fullname)) print("Public {0!s}".format(pubkey))
print("Email: {0!s}".format(email))
print("Public {0!s}".format(pubkey)) validation = input("\nIs this information correct? [y/N]")
while not re.match("[yYnN\n]", validation):
print("Please answer y for yes or n for no")
validation = input("\nIs this information correct? [y/N]") validation = input("Is this information correct? [y/N]")
while not re.match("[yYnN\n]", validation): if re.match("[yY]", validation):
print("Please answer y for yes or n for no") print("Thank you for your application! We'll get in touch shortly. 🐧")
validation = input("Is this information correct? [y/N]") try:
if re.match("[yY]", validation): connection=sqlite3.connect(REG_FILE)
print("Thank you for your application! We'll get in touch shortly. 🐧") cursor=connection.cursor()
try: __checkSQLite(cursor, connection)
connection=sqlite3.connect(REG_FILE) addtotable(cursor, connection, username, fullname, email, pubkey)
cursor=connection.cursor() connection.commit()
__checkSQLite(cursor, connection) connection.close()
addtotable(cursor, connection, username, fullname, email, pubkey) except sqlite3.Error as e:
connection.commit() logging.exception("Database {0!s} couldnt be accessed or created. Exception: {0!s}".
connection.close() format(config['DEFAULT']['applications_db'], e))
except: if connection:
logging.exception("Database {0!s} couldnt be accessed or created. Exception:".format(config['DEFAULT']['applications_db'])) connection.close()
connection.close() exit(1)
exit(1)
pass return 0
return 0
if __name__ == "__main__": if __name__ == "__main__":
try: try:
main() main()
exit(0) exit(0)
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass

Loading…
Cancel
Save