forked from tilde/ssh-reg
Compare commits
15 Commits
master
...
feature-te
Author | SHA1 | Date |
---|---|---|
Darksider3 | f803b1acb4 | 5 years ago |
Darksider3 | cabe14d41d | 5 years ago |
Darksider3 | c954940bec | 5 years ago |
Darksider3 | b4d52b5376 | 5 years ago |
Darksider3 | c79edbfc84 | 5 years ago |
Darksider3 | 3a6a92267b | 5 years ago |
Darksider3 | f201ab603d | 5 years ago |
Darksider3 | b8d4dac5da | 5 years ago |
Darksider3 | e2c2bcb0c2 | 5 years ago |
Darksider3 | 108492db3f | 5 years ago |
Darksider3 | d2f99d95d0 | 5 years ago |
Darksider3 | fb620447c7 | 5 years ago |
Darksider3 | b4bb45ef85 | 5 years ago |
Darksider3 | aae7504e13 | 5 years ago |
Darksider3 | b5c11455d0 | 5 years ago |
@ -1,4 +1,5 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
.idea/
|
.idea/
|
||||||
test*
|
test*
|
||||||
|
!test/
|
||||||
|
!test_*.py
|
||||||
|
@ -1,120 +1,41 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import configparser
|
import configparser
|
||||||
import sqlite3 # sqlite3.Row-Object
|
|
||||||
from typing import List # Typing support!
|
|
||||||
|
|
||||||
import lib.uis.default as default_cmd # Follows -u, -a, -f flags
|
import lib.uis.default as default_cmd # Follows -u, -a, -f flags
|
||||||
from lib.sqlitedb import SQLiteDB
|
from lib.ListUsers import ListUsers
|
||||||
|
|
||||||
|
|
||||||
class ListUsers:
|
|
||||||
db = None
|
|
||||||
usersFetch = None
|
|
||||||
|
|
||||||
def __init__(self, db: str, unapproved: bool = False, approved: bool = True, single_user: str = None):
|
|
||||||
"""Constructs ListUsers
|
|
||||||
|
|
||||||
:param db: Database to access
|
|
||||||
:type db: str
|
|
||||||
:param unapproved: only List unapproved users
|
|
||||||
:type unapproved: bool
|
|
||||||
:param approved: only list approved users
|
|
||||||
:type approved: bool
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.db = SQLiteDB(db)
|
|
||||||
if unapproved: # only unapproved users
|
|
||||||
query = "SELECT * FROM `applications` WHERE `status` = '0'"
|
|
||||||
elif approved: # Approved users
|
|
||||||
query = "SELECT * FROM `applications` WHERE `status` = '1'"
|
|
||||||
else: # All users
|
|
||||||
query = "SELECT * FROM `applications`"
|
|
||||||
self.usersFetch = self.db.query(query)
|
|
||||||
if single_user is not None:
|
|
||||||
query = "SELECT * FROM `applications` WHERE `username` = ?"
|
|
||||||
self.usersFetch = self.db.safequery(query, tuple([single_user]))
|
|
||||||
|
|
||||||
def output_as_list(self) -> str:
|
|
||||||
"""Generates a string with one (approved) user per line and one newline at the end
|
|
||||||
|
|
||||||
:rtype: str
|
|
||||||
:return: String consisting with one(activated) user per line
|
|
||||||
"""
|
|
||||||
|
|
||||||
list_str: str = ""
|
|
||||||
query = "SELECT `username` FROM `applications` WHERE `status` = '1' ORDER BY timestamp ASC"
|
|
||||||
self.usersFetch = self.db.query(query)
|
|
||||||
for users in self.usersFetch:
|
|
||||||
list_str += users["username"] + "\n"
|
|
||||||
return list_str
|
|
||||||
|
|
||||||
def prettyPrint(self) -> None:
|
|
||||||
pass # see below why not implemented yet, texttable...
|
|
||||||
|
|
||||||
def get_fetch(self) -> List[sqlite3.Row]:
|
|
||||||
""" Returns a complete fetch done by the lib.sqlitedb-class
|
|
||||||
|
|
||||||
:return: Complete fetchall(). A List[sqlite3.Row] with dict-emulation objects.
|
|
||||||
:rtype: List[sqlite3.Row]
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self.usersFetch
|
|
||||||
|
|
||||||
|
|
||||||
# @TODO MAYBE best solution: https://pypi.org/project/texttable/
|
|
||||||
# examle:
|
|
||||||
"""
|
|
||||||
from texttable import Texttable
|
|
||||||
t = Texttable()
|
|
||||||
t.add_rows([['Name', 'Age'], ['Alice', 24], ['Bob', 19]])
|
|
||||||
print(t.draw())
|
|
||||||
---------------> Results in:
|
|
||||||
|
|
||||||
+-------+-----+
|
|
||||||
| Name | Age |
|
|
||||||
+=======+=====+
|
|
||||||
| Alice | 24 |
|
|
||||||
+-------+-----+
|
|
||||||
| Bob | 19 |
|
|
||||||
+-------+-----+
|
|
||||||
|
|
||||||
for user in fetch:
|
|
||||||
print("ID: {}; Username: \"{}\"; Mail: {}; Name: \"{}\"; Registered: {}; Status: {}".format(
|
|
||||||
user["id"], user["username"], user["email"], user["name"], user["timestamp"], user["status"]
|
|
||||||
))
|
|
||||||
"""
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
default_cmd.argparser.description += " - Lists Users from the Tilde database."
|
default_cmd.argparser.description += " - Lists Users from the Tilde database."
|
||||||
default_cmd.argparser.add_argument('--list-asc', default=False, action="store_true",
|
default_cmd.argparser.add_argument('--list-asc', default=False, action="store_true",
|
||||||
help='Output a newline seperated list of users', required=False, dest="args_asc")
|
help='Output a newline seperated list of users', required=False, dest="args_asc")
|
||||||
default_cmd.argparser.add_argument('--user', default=None, type=str,
|
default_cmd.argparser.add_argument('--single_user', default=None, type=str,
|
||||||
help="Just show a specific user by it's name", required=False)
|
help="Just show a specific single_user by it's name", required=False)
|
||||||
args = default_cmd.argparser.parse_args()
|
args = default_cmd.argparser.parse_args()
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read(args.config)
|
config.read(args.config)
|
||||||
|
|
||||||
ret = ""
|
OUTPUT = ""
|
||||||
if args.user is not None:
|
if args.single_user is not None:
|
||||||
L = ListUsers(config['DEFAULT']['applications_db'], unapproved=args.unapproved, approved=args.approved,
|
L = ListUsers(config['DEFAULT']['applications_db'], unapproved=args.unapproved, approved=args.approved,
|
||||||
single_user=args.user)
|
single_user=args.single_user)
|
||||||
else:
|
else:
|
||||||
L = ListUsers(config['DEFAULT']['applications_db'], unapproved=args.unapproved, approved=args.approved)
|
L = ListUsers(config['DEFAULT']['applications_db'], unapproved=args.unapproved, approved=args.approved)
|
||||||
if args.args_asc:
|
if args.args_asc:
|
||||||
ret = L.output_as_list()
|
OUTPUT = L.output_as_list()
|
||||||
else:
|
else:
|
||||||
fetch = L.get_fetch()
|
users = L.get_fetch()
|
||||||
ret += "ID %-1s| Username %-5s| Mail %-20s| Name %-17s| Registered %-8s | State |\n" % (
|
OUTPUT += "ID %-1s| Username %-5s| Mail %-20s| Name %-17s| Registered %-8s | State |\n" % (
|
||||||
" ", " ", " ", " ", " "
|
" ", " ", " ", " ", " "
|
||||||
)
|
)
|
||||||
ret += 102 * "-" + "\n"
|
OUTPUT += 102 * "-" + "\n"
|
||||||
for user in fetch:
|
for single_user in users:
|
||||||
ret += "%-4i| %-14s| %-25s| %-22s| %-8s | %-5i |\n" % (
|
OUTPUT += "%-4i| %-14s| %-25s| %-22s| %-8s | %-5i |\n" % (
|
||||||
user["id"], user["username"], user["email"], user["name"], user["timestamp"], user["status"]
|
single_user["id"], single_user["username"], single_user["email"],
|
||||||
|
single_user["name"], single_user["timestamp"], single_user["status"]
|
||||||
)
|
)
|
||||||
if args.file != "stdout":
|
if args.file != "stdout":
|
||||||
with open(args.file, 'w') as f:
|
with open(args.file, 'w') as f:
|
||||||
print(ret, file=f)
|
print(OUTPUT, file=f)
|
||||||
else:
|
else:
|
||||||
print(ret)
|
print(OUTPUT)
|
||||||
exit(0)
|
exit(0)
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
from lib.sqlitedb import SQLiteDB
|
||||||
|
import sqlite3 # sqlite3.Row-Object
|
||||||
|
from typing import List # Typing support!
|
||||||
|
|
||||||
|
|
||||||
|
class ListUsers:
|
||||||
|
"""
|
||||||
|
List tilde users
|
||||||
|
"""
|
||||||
|
|
||||||
|
db = None
|
||||||
|
users_fetch = None
|
||||||
|
|
||||||
|
def __init__(self, db: str, unapproved: bool = False, approved: bool = True, single_user: str = None):
|
||||||
|
"""Constructs list_users
|
||||||
|
|
||||||
|
:param db: Database to access
|
||||||
|
:type db: str
|
||||||
|
:param unapproved: only List unapproved users
|
||||||
|
:type unapproved: bool
|
||||||
|
:param approved: only list approved users
|
||||||
|
:type approved: bool
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.db = SQLiteDB(db)
|
||||||
|
if unapproved: # only unapproved users
|
||||||
|
query = "SELECT * FROM `applications` WHERE `status` = '0'"
|
||||||
|
elif approved: # Approved users
|
||||||
|
query = "SELECT * FROM `applications` WHERE `status` = '1'"
|
||||||
|
else: # All users
|
||||||
|
query = "SELECT * FROM `applications`"
|
||||||
|
self.users_fetch = self.db.query(query)
|
||||||
|
if single_user is not None:
|
||||||
|
query = "SELECT * FROM `applications` WHERE `username` = ?"
|
||||||
|
self.users_fetch = self.db.safe_query(query, tuple([single_user]))
|
||||||
|
|
||||||
|
def output_as_list(self) -> str:
|
||||||
|
"""Generates a string with one (approved) single_user per line and one newline at the end
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
:return: String consisting with one(activated) single_user per line
|
||||||
|
"""
|
||||||
|
|
||||||
|
list_str: str = ""
|
||||||
|
query = "SELECT `username` FROM `applications` WHERE `status` = '1' ORDER BY timestamp ASC"
|
||||||
|
self.users_fetch = self.db.query(query)
|
||||||
|
for user in self.users_fetch:
|
||||||
|
list_str += user["username"] + "\n"
|
||||||
|
return list_str
|
||||||
|
|
||||||
|
def pretty_print(self) -> None:
|
||||||
|
"""
|
||||||
|
pretty-print users
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
pass # see below why not implemented yet, texttable...
|
||||||
|
|
||||||
|
def get_fetch(self) -> List[sqlite3.Row]:
|
||||||
|
""" Returns a complete users done by the lib.sqlitedb-class
|
||||||
|
|
||||||
|
:return: Complete fetchall(). A List[sqlite3.Row] with dict-emulation objects.
|
||||||
|
:rtype: List[sqlite3.Row]
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.users_fetch
|
@ -1,6 +1,9 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import lib.cwd
|
import lib.cwd
|
||||||
|
|
||||||
argparser = argparse.ArgumentParser(description='Tilde administration tools ', conflict_handler="resolve")
|
argparser = argparse.ArgumentParser(description='Tilde administration tools ',
|
||||||
|
conflict_handler="resolve")
|
||||||
argparser.add_argument('-c', '--config', default=lib.cwd.cwd,
|
argparser.add_argument('-c', '--config', default=lib.cwd.cwd,
|
||||||
type=str, help='Path to configuration file', required=False)
|
type=str,
|
||||||
|
help='Path to configuration file. If not set, we look for it in $TILDE_CONF',
|
||||||
|
required=False)
|
||||||
|
Binary file not shown.
@ -0,0 +1,47 @@
|
|||||||
|
import unittest
|
||||||
|
import test.testcfg as testcfg
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from lib.ListUsers import ListUsers
|
||||||
|
sys.path.append('..')
|
||||||
|
|
||||||
|
|
||||||
|
class TestListUsers(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
try:
|
||||||
|
self.list = ListUsers(testcfg.test_db, unapproved=False, approved=False)
|
||||||
|
except IOError as fs_err:
|
||||||
|
self.fail(fs_err)
|
||||||
|
|
||||||
|
def test_singleUser(self):
|
||||||
|
try:
|
||||||
|
ListUsers(testcfg.test_db, single_user=testcfg.assured_user)
|
||||||
|
except Exception:
|
||||||
|
self.fail()
|
||||||
|
|
||||||
|
def test_output_as_list(self):
|
||||||
|
# count newlines in string, everything under 3 is wrong, and above 20 too.
|
||||||
|
out = self.list.output_as_list().splitlines()
|
||||||
|
self.assertGreater(len(out), testcfg.ListUsers_output_newlines,
|
||||||
|
"Newlines in OUTPUT doesn't exceed minimum of at least "
|
||||||
|
f"{testcfg.ListUsers_output_newlines} "
|
||||||
|
"lines!")
|
||||||
|
|
||||||
|
def test_pretty_print(self):
|
||||||
|
# wont going to compare the stdout sorry very much
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_get_fetch(self):
|
||||||
|
fetch = self.list.get_fetch()
|
||||||
|
self.assertIsInstance(fetch, list)
|
||||||
|
self.assertGreater(len(fetch),
|
||||||
|
testcfg.ListUsers_fetch_size_min, "fetch is NOT greater than"
|
||||||
|
"the configured fetch minimum")
|
||||||
|
try:
|
||||||
|
fetch[0]
|
||||||
|
except (KeyError, IOError) as suddenly_not_there:
|
||||||
|
self.fail(f"Expected fetch to have at least one argument! {suddenly_not_there}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@ -0,0 +1,76 @@
|
|||||||
|
import sys
|
||||||
|
sys.path.append('..')
|
||||||
|
import unittest
|
||||||
|
import lib.Validator
|
||||||
|
import test.testcfg as testcfg
|
||||||
|
|
||||||
|
|
||||||
|
class TestValidator(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
self.validator = lib.Validator
|
||||||
|
|
||||||
|
def test_check_username_characters(self):
|
||||||
|
for name in testcfg.Validator_Valid_Users_Chars_List:
|
||||||
|
self.assertTrue(self.validator.checkUsernameCharacters(name))
|
||||||
|
for name in testcfg.Validator_Invalid_Users_Chars_List:
|
||||||
|
self.assertFalse(self.validator.checkUsernameCharacters(name), name)
|
||||||
|
|
||||||
|
for name in testcfg.genRandomString():
|
||||||
|
self.assertFalse(self.validator.checkUsernameCharacters(name), name)
|
||||||
|
|
||||||
|
def test_check_username_length(self):
|
||||||
|
for name in testcfg.Validator_Valid_Users_Length:
|
||||||
|
self.assertTrue(self.validator.checkUsernameLength(name))
|
||||||
|
for name in testcfg.Validator_Invalid_Users_Length:
|
||||||
|
self.assertFalse(self.validator.checkUsernameLength(name), name)
|
||||||
|
|
||||||
|
def test_check_email(self):
|
||||||
|
for name in testcfg.Validator_Valid_Mail:
|
||||||
|
self.assertTrue(self.validator.checkEmail(name))
|
||||||
|
for name in testcfg.Validator_Invalid_Mail:
|
||||||
|
self.assertFalse(self.validator.checkEmail(name), name)
|
||||||
|
|
||||||
|
for name in testcfg.genRandomString():
|
||||||
|
self.assertFalse(self.validator.checkEmail(name))
|
||||||
|
|
||||||
|
def test_check_user_exists(self):
|
||||||
|
self.assertTrue(self.validator.checkUserExists("root"))
|
||||||
|
self.assertTrue(self.validator.checkUserExists("nobody")) # remove in case there exists an actual system without
|
||||||
|
|
||||||
|
for User in testcfg.genRandomString():
|
||||||
|
self.assertFalse(self.validator.checkUserExists(User))
|
||||||
|
|
||||||
|
def test_check_user_in_db(self):
|
||||||
|
for name in testcfg.Validator_db_user_exists:
|
||||||
|
self.assertTrue(self.validator.checkUserInDB(name, testcfg.test_db))
|
||||||
|
|
||||||
|
for name in testcfg.Validator_db_user_inexistent:
|
||||||
|
self.assertFalse(self.validator.checkUserInDB(name, testcfg.test_db))
|
||||||
|
|
||||||
|
def test_check_sshkey(self):
|
||||||
|
for key in testcfg.Validator_valid_ssh:
|
||||||
|
self.assertTrue(self.validator.checkSSHKey(key))
|
||||||
|
for key in testcfg.Validator_invalid_ssh:
|
||||||
|
self.assertFalse(self.validator.checkSSHKey(key))
|
||||||
|
|
||||||
|
def test_check_datetime_format(self):
|
||||||
|
for cur in testcfg.Validator_valid_datetime:
|
||||||
|
self.assertTrue(self.validator.checkDatetimeFormat(cur))
|
||||||
|
for cur in testcfg.Validator_invalid_checkname_names:
|
||||||
|
self.assertFalse(self.validator.checkDatetimeFormat(cur))
|
||||||
|
for cur in testcfg.genRandomString():
|
||||||
|
self.assertFalse(self.validator.checkDatetimeFormat(cur))
|
||||||
|
|
||||||
|
def test_check_name(self):
|
||||||
|
for name in testcfg.Validator_valid_checkname_names:
|
||||||
|
self.assertTrue(self.validator.checkName(name))
|
||||||
|
for name in testcfg.Validator_invalid_checkname_names:
|
||||||
|
self.assertFalse(self.validator.checkName(name))
|
||||||
|
for name in testcfg.genRandomString(alphabet="\n\b\r\t\f"):
|
||||||
|
self.assertFalse(self.validator.checkName(name))
|
||||||
|
|
||||||
|
def test_check_import_file(self):
|
||||||
|
self.assertTrue(self.validator.checkImportFile(testcfg.test_import_csv,
|
||||||
|
testcfg.test_db))
|
||||||
|
if not self.validator.checkImportFile(testcfg.test_import_invalid_csv, testcfg.test_db):
|
||||||
|
self.fail("Invalid import file should've failed the test")
|
@ -0,0 +1,50 @@
|
|||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
import csv
|
||||||
|
import backup
|
||||||
|
sys.path.append('..')
|
||||||
|
from lib.ListUsers import ListUsers
|
||||||
|
import test.testcfg as testcfg
|
||||||
|
|
||||||
|
class TestBackup(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
try:
|
||||||
|
self.fetch = ListUsers(testcfg.test_db, unapproved=False, approved=False).get_fetch()
|
||||||
|
self.Backup = backup.Backup(testcfg.test_backup_csv)
|
||||||
|
except Exception as general_setup:
|
||||||
|
self.fail(f"Failed setup already! {general_setup}")
|
||||||
|
|
||||||
|
def test_set_dialect(self):
|
||||||
|
self.Backup.set_dialect("excel")
|
||||||
|
self.assertEqual(self.Backup.dialect, "excel")
|
||||||
|
|
||||||
|
def test_set_quoting(self):
|
||||||
|
self.Backup.set_quoting(csv.QUOTE_NONNUMERIC)
|
||||||
|
self.assertEqual(self.Backup.quoting, csv.QUOTE_NONNUMERIC)
|
||||||
|
|
||||||
|
def test_set_filename(self):
|
||||||
|
self.Backup.set_filename(testcfg.test_backup_csv)
|
||||||
|
self.assertEqual(self.Backup.filename, testcfg.test_backup_csv)
|
||||||
|
self.Backup.set_field_names(self.fetch[0].keys())
|
||||||
|
|
||||||
|
def test_set_field_names(self):
|
||||||
|
# @TODO: Dynamic! Having a test scheme from which we setup our test is beneficial here, also values
|
||||||
|
self.Backup.set_field_names(self.fetch[0].keys())
|
||||||
|
keys_found = self.Backup.field_names
|
||||||
|
self.assertEqual(keys_found, ['id', 'username', 'email', 'name', 'pubkey', 'timestamp', 'status'])
|
||||||
|
|
||||||
|
def test_backup_to_file(self):
|
||||||
|
try:
|
||||||
|
self.Backup.set_field_names(self.fetch[0].keys())
|
||||||
|
self.Backup.backup_to_file(self.fetch)
|
||||||
|
self.assertTrue(os.path.exists(testcfg.test_backup_csv),
|
||||||
|
"Assert True that file exists and was written")
|
||||||
|
os.unlink(os.path.realpath(testcfg.test_backup_csv))
|
||||||
|
except IOError as io_error:
|
||||||
|
self.fail(io_error)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@ -0,0 +1,30 @@
|
|||||||
|
"id","username","email","name","pubkey","timestamp","status"
|
||||||
|
1,"darksider1","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 16:12:52",1
|
||||||
|
1,"darksider2","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 12:11:52",1
|
||||||
|
1,"darksider3","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 13:14:52",0
|
||||||
|
1,"darksider4","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 14:15:52",1
|
||||||
|
1,"darksider5","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 15:19:52",1
|
||||||
|
1,"darksider6","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 16:12:52",1
|
||||||
|
1,"darksider7","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 17:11:52",0
|
||||||
|
1,"darksider8","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 18:14:52",1
|
||||||
|
1,"darksider9","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 19:15:52",1
|
||||||
|
1,"darksider10","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 20:19:52",1
|
||||||
|
1,"darksider11","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 21:12:52",0
|
||||||
|
1,"darksider12","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 22:11:52",1
|
||||||
|
1,"darksider13","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 23:14:52",0
|
||||||
|
1,"darksider14","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 00:15:52",1
|
||||||
|
1,"darksider15","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 01:19:52",0
|
||||||
|
1,"darksider16","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 03:15:52",1
|
||||||
|
1,"darksider17","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 02:19:52",1
|
||||||
|
1,"darksider18","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 05:12:52",0
|
||||||
|
1,"darksider19","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 04:11:52",1
|
||||||
|
1,"darksider20","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 06:14:52",0
|
||||||
|
1,"darksider21","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 07:15:52",1
|
||||||
|
1,"darksider22","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 09:19:52",0
|
||||||
|
1,"darksider23","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 08:15:52",1
|
||||||
|
1,"darksider24","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 10:19:52",1
|
||||||
|
1,"darksider25","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 11:12:52",0
|
||||||
|
1,"darksider26","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 12:11:52",1
|
||||||
|
1,"darksider27","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 13:14:52",0
|
||||||
|
1,"darksider28","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 14:15:52",1
|
||||||
|
1,"darksider29","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 15:19:52",0
|
|
@ -0,0 +1,14 @@
|
|||||||
|
"id","username","email","name","pubkey","timestamp","status"
|
||||||
|
1,"darksider3","tester@testentry.de","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro","2019-10-12 11:19:52",6
|
||||||
|
2,"Darksider2","notapproved@tester.com","Unapproved Tester","Unknown","2019-10-12 11:20:34",6
|
||||||
|
3,"darksider4","penis@cocksucker.email","Luca","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFsOkf8NTRY++69dCMO8hJslNCWIJMhgHxwN4vSPUG2 drip@kvn.home.steinke.pro",12345,1
|
||||||
|
4,"darksider5","pissfotze@example.com","empty","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOf5ZbbXbTyVD1WN0XES3lPG9jXGoYxcKhXPBq5D3ZwG test@example-com","1970-00-00",0
|
||||||
|
7,"3kliksphilip","test@test",,"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIjb0JardY8xeB5YwIPn9Z0HSEPfy3wEIB90f/rEgy33 test@example.com","11.10.20 20:20",1
|
||||||
|
8,"root","mailtest@tester.testets.test","Tester sagtHallo","ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBiR1xpeeBuKALRi1czgVbyPbGW7Y6It72PRULFDhiFM drip@kvn.home.steinke.pro","10.12.23 13:37",0
|
||||||
|
6213663,"4kliksphilip",,"Testtest","test@example.com nokey","12.10.19 01:15",1
|
||||||
|
11,"name mitleerzeichen","test","Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.","Unknown","1970-00-00",-7
|
||||||
|
8,"$HOME","wurst",,"invalid",1,3
|
||||||
|
12,"loremipsumdolorsitametconsetetursadipisceoraetorbi","eierkopf",,";;--",2,4
|
||||||
|
16,"darksider3","penis@darksider3.de",,,1970,200
|
||||||
|
-1,"darksider17","haha@lol.nigge.rs",,,"penis",6
|
||||||
|
|
|
Loading…
Reference in New Issue