Guest User

Untitled

a guest
Jan 14th, 2018
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.83 KB | None | 0 0
  1. '''Staff management.'''
  2.  
  3. import time
  4. from sqlalchemy.sql import case, or_, and_, select, func, null
  5.  
  6. import strings
  7. import model
  8. import misc
  9. import staff_interface
  10. import config, config_defaults
  11. from util import WakaError, local
  12. from template import Template
  13.  
  14. # Cache of staff personnel objects.
  15. __staff = {}
  16.  
  17. # Staff class types.
  18. ADMIN = 'admin'
  19. GLOBAL_MOD = 'globmod'
  20. MODERATOR = 'mod'
  21. CLASSES = (ADMIN, GLOBAL_MOD, MODERATOR)
  22.  
  23. # Login cookie expire times (in seconds).
  24. SAVED_LOGIN_EXPIRE = 365 * 24 * 3600
  25. UNSAVED_LOGIN_EXPIRE = 3600
  26.  
  27. # Staff Accounts and Logins
  28. class LoginData(object):
  29.     '''Class for interfacing with prefetched login data.'''
  30.  
  31.     def __init__(self, user, addr):
  32.         self.__addr = addr
  33.         self.__crypt = misc.hide_critical_data\
  34.                        (','.join((user.password, remote)), config.SECRET)
  35.         self.__username = user.username
  36.         self.__cstring = ','.join((self.username, self.crypt()))
  37.  
  38.     def make_cookie(self, save_login=False):
  39.         misc.make_cookies(admin=self.__cstring)
  40.  
  41.         if save_login:
  42.             misc.make_cookies(wakaadminsave='1', wakaadmin=crypt,
  43.                               expires=time.time()+SAVED_LOGIN_EXPIRE)
  44.         else:
  45.             misc.make_cookies(wakaadminsave='0', wakaadmin=crypt,
  46.                               expires=time.time()+UNSAVED_LOGIN_EXPIRE)
  47.  
  48.  
  49.     def get_crypt(self):
  50.         '''Encrypted <password + MAC> string for login credentials.'''
  51.  
  52.         return self.__crypt
  53.  
  54.     def get_cookie_str(self):
  55.         return self.__cstring
  56.  
  57.     def get_addr(self):
  58.         return self.__addr
  59.  
  60.     def get_username(self):
  61.         return self.__username
  62.  
  63.     cookie_str = property(get_cookie_str)
  64.     crypt = property(get_crypt)
  65.     addr = property(get_addr)
  66.     username = property(get_username)
  67.  
  68. def get_staff(username):
  69.     '''Generate (or get) a cached staff object for initializing and
  70.    updating account information.'''
  71.  
  72.     if username in __staff:
  73.         return __staff[username]
  74.  
  75.     # Class for representing staff
  76.     class StaffMember(object):
  77.         def __init__(self, username):
  78.             session = model.Session()
  79.             table = model.account
  80.             table.create(bind=model.engine, checkfirst=True)
  81.             sql = table.select().where(table.c.username == username)
  82.             row = session.execute(sql).fetchone()
  83.             self.__table = table
  84.  
  85.             if row is None:
  86.                 WakaError('Staff not found.')
  87.  
  88.             # Grab parameters from database. Password is pre-encrypted.
  89.             self.__username = username
  90.             self.__password = row.password
  91.             self.__class = row.account
  92.             self.__reign = row.reign.split(',')
  93.             self.__disabled = row.disabled
  94.             self.__update_dict = {}
  95.  
  96.             # Not logged in yet.
  97.             self.__login_data = None
  98.  
  99.         def __update_db(self, **kwargs):
  100.             self.__update_dict += kwargs
  101.  
  102.         def get_username(self):
  103.             return self.__username
  104.  
  105.         def get_password(self):
  106.             return self.__password
  107.  
  108.         def set_password(self, new):
  109.             table = self.__table
  110.             # TODO: Sanity checks
  111.  
  112.             kwargs = {'password' : new}
  113.             self.__update_db(**kwargs)
  114.             self.__password = new
  115.  
  116.         def get_reign(self):
  117.             return self.__reign
  118.  
  119.         def set_reign(self, board_list):
  120.             reign_str = ','.join(board_list)
  121.             kwargs = {'reign' : reign_str}
  122.             self.__update_db(**kwargs)
  123.  
  124.             self.__reign = board_list
  125.  
  126.         def get_class(self):
  127.             return self.__class
  128.  
  129.         def set_class(self, new):
  130.             if new in CLASSES:
  131.                 kwargs = {'account' : new}
  132.                 self.__update_db(**kwargs)
  133.                 self.__class = new
  134.             else:
  135.                 raise WakaError('Invalid class name %s' % new)
  136.  
  137.         def get_login_data(self):
  138.             return self.__login_data
  139.  
  140.         def get_disabled(self):
  141.             return self.__disabled
  142.  
  143.         def set_disabled(self, disable):
  144.             if disable:
  145.                 kwargs = {'disabled' : 1}
  146.             else:
  147.                 kwargs = {'disabled' : 0}
  148.             self.__disabled = disable
  149.  
  150.             self.__update_db(**kwargs)
  151.  
  152.         def login_host(self, ip):
  153.             login_data = LoginData(self.username, ip)
  154.             self.__login_data = login_data
  155.             return login_data
  156.  
  157.         def logout_user(self):
  158.             self.__login_data = None
  159.  
  160.         def flush_db(self):
  161.             session = model.Session()
  162.             table = self.__table
  163.  
  164.             if len(self.__update_dict) > 0:
  165.                 db_update = table.update().where(self.username == username)\
  166.                                  .values(**self.__update_dict)
  167.  
  168.         account = property(get_class, set_class)
  169.         username = property(get_username)
  170.         password = property(get_password, set_password)
  171.         reign = property(get_reign, set_reign)
  172.         disabled = property(get_disabled, set_disabled)
  173.  
  174.     staff_obj = StaffMember(username)
  175.     __staff[username] = staff_obj
  176.     return staff_obj
  177.  
  178. def add_staff(username, pt_password, account, reign):
  179.     session = model.Session()
  180.     table = model.account
  181.     password = misc.hide_critical_data(pt_password, config.SECRET)
  182.     reign_str = ','.join(reign)
  183.  
  184.     sql = table.insert().values(username=username, password=password,
  185.                                 account=account, reign=reign_str,
  186.                                 disabled=0)
  187.     session.execute(sql)
  188.  
  189. def del_staff(username):
  190.     session = model.Session()
  191.     table = model.account
  192.     sql = table.delete(table.c.username == username)
  193.     session.execute(sql)
  194.  
  195.     try:
  196.         del __staff[username]
  197.     except AttributeError:
  198.         pass
  199.  
  200. def edit_staff(mpass, username, clear_pass=None, new_class=None,
  201.                reign=None):
  202.  
  203.     staff_obj = get_staff(username)
  204.    
  205.     if clear_pass:
  206.         staff_obj.password = misc.hide_critical_data(clear_pass,
  207.                                                      config.SECRET)
  208.  
  209.     if new_class and new_class in CLASSES:
  210.         staff_obj.account = new_class
  211.  
  212.     if reign:
  213.         staff_obj.reign = reign
  214.  
  215.     staff_obj.flush_db()
  216.  
  217. def staff_exist():
  218.     session = model.Session()
  219.     table = model.account
  220.     table.create(bind=model.engine, checkfirst=True)
  221.     sql = select([func.count()], table)
  222.     row = session.execute(sql).fetchone()
  223.  
  224.     if row[0] == 0:
  225.         return False
  226.     else:
  227.         return True
  228.  
  229.  
  230. def do_login(username=None, password=None, save_login=False,
  231.              admin_cookie=None, nexttask='mpanel'):
  232.  
  233.     bad_pass = False
  234.     staff_entry = None
  235.  
  236.     if len(__staff) == 0 and not staff_exist():
  237.         return staff_interface.make_first_time_setup_gateway()
  238.     elif username and password:
  239.         # Login via login form entry.
  240.         try:
  241.             staff_entry = get_staff(username)
  242.         except WakaError:
  243.             # Bad username.
  244.             bad_pass = True
  245.         else:
  246.             crypt_pass = misc.hide_critical_data(staff_entry.password,
  247.                                                  config.SECRET)
  248.             if crypt_pass == staff_entry.password:
  249.                 staff_entry.login_host(remote)
  250.             else:
  251.                 bad_pass = True
  252.     elif admin_cookie:
  253.         # Attempt automatic login.
  254.         staff_entry = check_password(admin_cookie, nexttask)
  255.     else:
  256.         # No login credentials given.
  257.         bad_pass = True
  258.  
  259.     if bad_pass:
  260.         return staff_interface.make_login_panel()
  261.     else:
  262.         login = staff_entry.login_data
  263.         login.make_cookie(save_login=save_login)
  264.         return staff_interface.make_admin_panel(login.cookie, nexttask)
  265.  
  266. def do_logout(admin):
  267.     # Clear login cache.
  268.     try:
  269.         user = check_password(admin)
  270.         user.logout_user()
  271.     except WakaError:
  272.         pass
  273.  
  274.     # Clear login cookies.
  275.     misc.make_cookies(wakaadmin='', wakaadminsave='0', expires=0)
  276.  
  277. def check_password(cookie_str, editing=None):
  278.     (username, crypt) = cookie_str.split(',')
  279.     staff_entry = get_staff(username)
  280.     cache = staff_entry.login_data
  281.  
  282.     if cache and cache.addr == remote:
  283.         # The host is already logged in.
  284.         pass
  285.     elif crypt != misc.hide_critical_data(','.join([staff_entry.password,
  286.                                                     remote]), config.SECRET):
  287.         WakaError(S_WRONGPASS)
  288.     else:
  289.         # NOTE: This will overwrite the current network address login.
  290.         staff_entry.login_host(remote)
  291.  
  292.     return staff_entry
  293.  
  294. def crypt_pass(cleartext):
  295.     remote = local.environ['REMOTE_ADDR']
  296.     return misc.hide_critical_data(','.join((cleartext, remote)),
  297.                                             config.SECRET)
Add Comment
Please, Sign In to add comment