scripts and tools to administer the lingy.in public unix / tilde
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
4.7KB

  1. import glob
  2. import json
  3. from flask import Flask, redirect, url_for, render_template, request
  4. # lyadmin
  5. # scripts and web form for a tilde / PAUS instance
  6. #
  7. # gashapwn
  8. # Nov 2020
  9. #
  10. # https://git.lain.church/gashapwn/lyadmin
  11. # gashapwn@protonmail.com
  12. # or
  13. # gasahwpn on irc.lainchan.org
  14. app=Flask(__name__)
  15. # Paths for conf file,
  16. # user list,
  17. # directory containing
  18. # account request files...
  19. WORKING_DIR = "/home/gashapwn/lyadmin/";
  20. ACCOUNT_DIR = "req/";
  21. FULL_PATH = str(WORKING_DIR) + str(ACCOUNT_DIR)
  22. CONF_PATH = str(WORKING_DIR) + "lyadmin.conf.json"
  23. # Account requests are given ID numbers
  24. # the first request will have the below
  25. # id number
  26. INIT_REQ_ID = "00000"
  27. # Slurp the conf file
  28. with open(CONF_PATH) as c: conf_json_str = c.read()
  29. conf_obj = json.loads(conf_json_str)
  30. # The main home page
  31. @app.route("/")
  32. def home():
  33. app.route('/')
  34. # Load the list of tilde users
  35. # to generate links for
  36. u_list = [];
  37. with open("user_list.txt") as u_file:
  38. for line in u_file.readlines():
  39. u_list.append(line.strip());
  40. return render_template("index.html", u_list=u_list, page_name="home")
  41. # The page with rules
  42. def rules():
  43. return render_template("rules.html")
  44. # Generate HTML for a form widget
  45. def widg_fun(widg):
  46. if(widg.w_type == "input"):
  47. # Return HTML for a single line input
  48. return "input id=id_%s name=%s type=text></input"%(widg.w_name, widg.w_name)
  49. elif(widg.w_type == "textarea"):
  50. # Return HTML for a big text input box
  51. return "textarea cols=40 id=id_%s name=%s rows=10 required=\"\""%(widg.w_name, widg.w_name)
  52. elif(widg.w_type == "check"):
  53. # Return HTML for a check box
  54. return "input id=id_%s name=%s type=checkbox required=\"\""%(widg.w_name, widg.w_name)
  55. return widg.w_type;
  56. # Generate HTML for request form
  57. # probably a strange way to do this...
  58. def req():
  59. app.route('/req')
  60. class Widg:
  61. def __init__(self, w_name, w_type, w_opt):
  62. self.w_name = w_name
  63. self.w_type = w_type
  64. self.w_opt = w_opt # only for choice type widg
  65. # Configuration for our request form
  66. rt = {
  67. "username": Widg("username", "input", None),
  68. "email for account lockout / registration confirmation (optional)": Widg("email", "input", None),
  69. "SSH public key": Widg("pub_key", "textarea", None),
  70. "shell of choice": Widg("shell", "choice", map(lambda k : (k, conf_obj["shell"][k]), list(conf_obj["shell"].keys()))),
  71. "have you read the rules?": Widg("rule_read", "check", None)
  72. };
  73. return render_template("req.html", req_tab = rt, widg_fun = widg_fun, page_name="req")
  74. # Process input from the /req page
  75. def signup():
  76. app.route('/req/signup')
  77. # Get all the params from the POST
  78. # request
  79. username = request.form["username"]
  80. email = request.form["email"]
  81. pub_key = request.form["pub_key"]
  82. shell = request.form["shell"]
  83. rule_read = request.form["rule_read"]
  84. is_email_user = False;
  85. # If a user didnt read the rules
  86. # send them back
  87. # Browser validations should
  88. # prevent this....
  89. if(rule_read != "on"):
  90. return redirect(url_for('req'))
  91. # Set placeholder if user didnt send an email
  92. if(len(email) > 1):
  93. is_email_user = True
  94. else:
  95. email = "NO_EMAIL"
  96. # All users requests have a sequential ID
  97. # this checks how many requests we have
  98. # and gives us a free ID so we can save
  99. # our request
  100. # This sets the ID of the request we're
  101. # abou to save to dsik
  102. if(len(glob.glob(ACCOUNT_DIR + str("[0-9]*ident*"))) == 0):
  103. new_id = int(INIT_REQ_ID)
  104. new_id_str = INIT_REQ_ID
  105. else:
  106. max_id = max(list(map( lambda path : path.split("/")[-1].split(".")[0] , glob.glob(str(ACCOUNT_DIR) + "[0-9]*ident*"))))
  107. # max_id = max(list(map( lambda path : path.split("/")[-1].split(".")[0] , glob.glob("./test/[0-9]*ident*"))))
  108. zpad = len(max_id)
  109. new_id = int(max_id)+1
  110. new_id_str = str(new_id).zfill(zpad)
  111. # write the request to disk
  112. fn1 = str(FULL_PATH) + str(new_id_str) + ".ident"
  113. with open(fn1, "w") as ident_file:
  114. ident_file.write(str(username) + "\n")
  115. ident_file.write(str(email) + "\n")
  116. ident_file.write(str(shell) + "\n")
  117. ident_file.write(str(pub_key) + "\n")
  118. return render_template("signup.html", is_email_user = is_email_user)
  119. @app.context_processor
  120. def get_site_name():
  121. return {"site_name": conf_obj["site_name"]}
  122. if __name__=="__main__":
  123. app.add_url_rule('/rules', 'rules', rules)
  124. app.add_url_rule('/req', 'req', req, methods = ['POST', 'GET'])
  125. app.add_url_rule('/req/signup', 'signup', signup, methods = ['POST'])
  126. app.run(host=conf_obj["listen_ip"],debug=True)