151 lines
6.3 KiB
Python
151 lines
6.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
|
|
# See LICENSE.txt for copyright info
|
|
|
|
from zope.interface import implements
|
|
from frn.manager import IManager
|
|
from twisted.python import log
|
|
from twisted.python.failure import Failure
|
|
from twisted.mail.smtp import sendmail
|
|
import random, string, uuid
|
|
from frn.user import FRNUser
|
|
|
|
def rndpasswd():
|
|
return ''.join([random.choice(string.ascii_uppercase) for i in range(8)])
|
|
|
|
class DatabaseManager(object):
|
|
|
|
implements(IManager)
|
|
|
|
def __init__(self, pool):
|
|
self._pool = pool
|
|
self._pool.runOperation("""
|
|
CREATE TABLE IF NOT EXISTS frn_users (
|
|
_id VARCHAR(32) NOT NULL PRIMARY KEY,
|
|
_ea VARCHAR(30) UNIQUE NOT NULL,
|
|
_pw VARCHAR(20) NOT NULL,
|
|
_on VARCHAR(20) NOT NULL,
|
|
_bc VARCHAR(20) NOT NULL,
|
|
_nn VARCHAR(20) NOT NULL,
|
|
_ct VARCHAR(20) NOT NULL,
|
|
_nt VARCHAR(20),
|
|
_ds VARCHAR(20) NOT NULL,
|
|
_ip VARCHAR(20),
|
|
registration TIMESTAMP NOT NULL DEFAULT current_timestamp,
|
|
lastlogin TIMESTAMP,
|
|
server VARCHAR(20),
|
|
port INTEGER
|
|
);
|
|
""")
|
|
self._pool.runOperation("""
|
|
CREATE TABLE IF NOT EXISTS frn_servers (
|
|
_vx VARCHAR(7) NOT NULL,
|
|
_sn VARCHAR(20) NOT NULL,
|
|
_pt INTEGER NOT NULL,
|
|
_bn VARCHAR(20),
|
|
_bp integer,
|
|
_ow VARCHAR(30) NOT NULL,
|
|
registration TIMESTAMP NOT NULL DEFAULT current_timestamp,
|
|
PRIMARY KEY(_sn, _pt)
|
|
);
|
|
""")
|
|
|
|
def serverLogin(self, server):
|
|
def checkauth(res):
|
|
if not isinstance(res, Failure):
|
|
if res[0] > 0:
|
|
return self._pool.runOperation("""
|
|
INSERT INTO frn_servers
|
|
(_vx, _sn, _pt, _bn, _bp, _ow) VALUES
|
|
(?,?,?,?,?,?)
|
|
""", (server.VX, server.SN, server.PT,
|
|
server.BN, server.BP, server.OW)).addCallbacks(
|
|
lambda x: 0, lambda x: -1)
|
|
else:
|
|
return -1
|
|
return self._pool.runQuery("SELECT count(*) FROM frn_users WHERE _ea=? AND _pw=?",
|
|
(server.OW, server.PW)).addBoth(checkauth)
|
|
|
|
def serverLogout(self, server):
|
|
self._pool.runOperation("UPDATE frn_users SET server=NULL, port=NULL, _nt=NULL WHERE server=? AND port=?",
|
|
(server.SN, server.PT))
|
|
self._pool.runOperation("DELETE FROM frn_servers WHERE _sn=? AND _pt=?",
|
|
(server.SN, server.PT))
|
|
|
|
def clientLogin(self, server, user):
|
|
def userfound(data):
|
|
log.msg("Client login: %s" % repr(data))
|
|
if data:
|
|
u = dict(zip(
|
|
('ID', 'EA', 'PW', 'ON', 'BC', 'NN', 'CT', 'NT', 'DS', 'IP', 'registration', 'lastlogin', 'server', 'port'),
|
|
data[0]))
|
|
if u['server']:
|
|
log.msg("Duplicate client %s" % repr(user))
|
|
return "DUPL"
|
|
self._pool.runQuery("""
|
|
UPDATE frn_users SET
|
|
_bc=?, _nn=?, _ct=?, _nt=?, _ds=?, _ip=?, server=?, port=?,
|
|
lastlogin=current_timestamp
|
|
WHERE _id=?
|
|
""", (user.BC, user.NN, user.CT, user.NT, user.DS, user.IP, server.SN, server.PT, u['ID']))
|
|
log.msg("Authenticated client %s" % repr(user))
|
|
return str(u['ID'])
|
|
else:
|
|
log.msg("Wrong client %s" % repr(user))
|
|
return "WRONG"
|
|
return self._pool.runQuery("SELECT * FROM frn_users WHERE _ea=? AND _on=? AND _pw=?",
|
|
(user.EA, user.ON, user.PW)).addCallbacks(userfound, lambda x: "WRONG")
|
|
|
|
def clientLogout(self, server, user):
|
|
log.msg("Logging out client %s" % repr(user))
|
|
return self._pool.runOperation("UPDATE frn_users SET server=NULL, port=NULL, _nt=NULL WHERE _id=?",
|
|
(user.ID,)).addBoth(lambda x: "OK")
|
|
|
|
def getClientList(self):
|
|
def buildlist(tr):
|
|
tr.execute("SELECT _sn, _pt FROM frn_servers")
|
|
servers = tr.fetchall()
|
|
r = {}
|
|
for sn, sp in servers:
|
|
r[(sn,sp)] = {}
|
|
tr.execute("SELECT DISTINCT _nt FROM frn_users WHERE server=? AND port=?", (sn,sp))
|
|
networks = tr.fetchall()
|
|
for (n,) in networks:
|
|
r[(sn,sp)][n] = []
|
|
tr.execute("SELECT _id, _on, _bc, _ds, _nn, _ct FROM frn_users WHERE server=? AND port=? AND _nt=?",
|
|
(sn, sp, n))
|
|
clients = tr.fetchall()
|
|
for c in clients:
|
|
cu = FRNUser(**dict(zip(['EA','ON','BC','DS','NN','CT'],c)))
|
|
r[(sn,sp)][n].append(cu)
|
|
return r
|
|
return self._pool.runInteraction(buildlist)
|
|
|
|
def registerUser(self, user):
|
|
def fetchdata(is_new):
|
|
def maildata(data):
|
|
u = dict(zip(
|
|
('ID', 'EA', 'PW', 'ON', 'BC', 'NN', 'CT', 'NT', 'DS', 'IP', 'registration', 'lastlogin', 'server', 'port'),
|
|
data[0]))
|
|
log.msg("Mailing password to user %s" % str(u))
|
|
with open('mailtemplate.txt','r') as tplfile:
|
|
tpl = tplfile.read()
|
|
mailbody = string.Template(tpl).safe_substitute(u)
|
|
sendmail('127.0.0.1',
|
|
'admin@gnuradionetwork.org',
|
|
[u['EA']],
|
|
mailbody, port=2525)
|
|
return "OK"
|
|
return self._pool.runQuery(
|
|
"SELECT * FROM frn_users WHERE _ea=?", (user.EA,)
|
|
).addCallback(maildata).addErrback(lambda x: "ERROR")
|
|
return self._pool.runOperation("""
|
|
INSERT INTO frn_users (_id, _ea, _pw, _on, _bc, _ds, _nn, _ct)
|
|
VALUES (?,?,?,?,?,?,?,?)
|
|
""", (uuid.uuid4().get_hex()[:20], user.EA, rndpasswd(),
|
|
user.ON, user.BC, user.DS, user.NN, user.CT)
|
|
).addBoth(fetchdata)
|
|
|
|
# vim: set et ai sw=4 ts=4 sts=4:
|