gnuradionetwork/frn/manager/database.py

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: