- initial client handling code
git-svn-id: file:///home/www/usr01/svn/gnuviechadmin/gnuviech.info/gnuviechadmin/trunk@213 a67ec6bc-e5d5-0310-a910-815c51eb3124
This commit is contained in:
parent
bf7992a600
commit
c84fc9a90c
62 changed files with 194 additions and 3086 deletions
1
AUTHOR
1
AUTHOR
|
@ -1 +0,0 @@
|
|||
Jan Dittberner <jan@dittberner.info>
|
340
LICENSE
340
LICENSE
|
@ -1,340 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
10
Makefile
10
Makefile
|
@ -1,10 +0,0 @@
|
|||
subdirs=php
|
||||
|
||||
all:
|
||||
|
||||
dumpdb:
|
||||
pg_dump -U gnuviech -h localhost -s -d -O gnuviechadmin > database.sql
|
||||
|
||||
clean:
|
||||
for i in $(subdirs); do make -C $$i clean; done
|
||||
-rm -f *~
|
33
README
33
README
|
@ -1,33 +0,0 @@
|
|||
gnuviechadmin aims to be a server administration tool originally
|
||||
developed for managing gnuviech.info.
|
||||
|
||||
gnuviechadmin is targeted for Debian GNU/Linux 3.0r2 (woody) but may
|
||||
be ported to later Debian GNU/Linux releases in the future.
|
||||
|
||||
application design thoughts
|
||||
===========================
|
||||
|
||||
I think a 2-layered architecture will be best.
|
||||
|
||||
One layer (which needs to be run as root) does all the background work
|
||||
(like creating users, zone files ...). This layer will be implemented
|
||||
in python and will invoke several Debian system utilities.
|
||||
|
||||
The second layer will in the first place be a PHP based Web frontend
|
||||
where the administrator can manage the servers most common
|
||||
tasks. Later there will be support for client and reseller frontends
|
||||
for tasks that the administrator allows them.
|
||||
|
||||
The second layer may also be a GUI application if the need arrises.
|
||||
|
||||
Both layers will be coupled through a sql database. I will use
|
||||
PostgreSQL, but as the need arrises I'll also try to support other
|
||||
databases.
|
||||
|
||||
|
||||
+----------+ +---------+
|
||||
| frontend | | backend |
|
||||
+-----+----+ +---+-----+
|
||||
| +----------+ |
|
||||
+--------->| database |<----------+
|
||||
+----------+
|
43
TODO
43
TODO
|
@ -1,43 +0,0 @@
|
|||
reseller management (NOT YET)
|
||||
|
||||
client management
|
||||
- add client
|
||||
- delete client
|
||||
- create bills
|
||||
- account traffic
|
||||
|
||||
dns management
|
||||
- add zones
|
||||
- whois search
|
||||
- register domains
|
||||
- add records
|
||||
- change records
|
||||
- delete records
|
||||
- delete zones
|
||||
|
||||
apache administration
|
||||
- associate domain with vhost entry
|
||||
- associate domain with path in vhost
|
||||
- special httpd.conf entries for host
|
||||
- logfile analysis
|
||||
- statistics per vhost
|
||||
|
||||
shell access (ssh)
|
||||
- allow input of rsa/dsa public keys in web frontend
|
||||
- set valid shell
|
||||
|
||||
imap/pop3 management
|
||||
- create pop3/imap mailbox for client with generated passwords
|
||||
- associate email address from client's domain to pop3/imap mailboxes
|
||||
|
||||
quota management
|
||||
- assign quotas to pop3/imap, diskspace for website and databases (if possible)
|
||||
|
||||
postgresql management
|
||||
- create databases for client
|
||||
|
||||
mysql management
|
||||
- create databases for client
|
||||
|
||||
statistics
|
||||
- create per user and per domain configuration for modlogan
|
|
@ -1,6 +0,0 @@
|
|||
USERPREFIX="usr"
|
||||
EXIMCONFDIR="etc/exim4/"
|
||||
VIRTUALDOMDIR=EXIMCONFDIR+"virtual/"
|
||||
POPHOMEDIR="/home/mail/"
|
||||
WEBHOMEDIR="/home/www/"
|
||||
DNSZONESDIR="/var/named-root/etc/"
|
|
@ -1,80 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import os, string
|
||||
|
||||
execfile('gvadm.preferences')
|
||||
|
||||
# if [ -n $USERPREFIX ]; then
|
||||
# USERPREFIX="usr"
|
||||
# fi
|
||||
#
|
||||
# if [ $1 == "" ]; then
|
||||
# echo "give <UserNumber>p<pop3Account> as parameter"
|
||||
# exit
|
||||
# fi
|
||||
#
|
||||
# NEWUSER="$USERPREFIX$1"
|
||||
# NEWHOME="/home/mail/$NEWUSER"
|
||||
# NEWPASS=$(apg -n 1 -a 1 -CL -m 8 -x 12)
|
||||
# echo $NEWHOME
|
||||
#
|
||||
# adduser --home "$NEWHOME" --shell /bin/true --no-create-home
|
||||
# --firstuid 20000 --ingroup poponly --disabled-password
|
||||
# --disabled-login --gecos "Popuser $NEWUSER" $NEWUSER
|
||||
#
|
||||
# mkdir -p "$NEWHOME"
|
||||
# chown -Rc $NEWUSER.poponly "$NEWHOME"
|
||||
# echo "${NEWUSER}:${NEWPASS}" | chpasswd
|
||||
#
|
||||
# echo "Herzlich willkommen auf dem GNU-Viech" |\
|
||||
# mail -s "Willkommen auf dem GNU-Viech" ${NEWUSER}
|
||||
#
|
||||
# echo added new pop3 user $NEWUSER with password $NEWPASS
|
||||
|
||||
def createpopaccount(domainname, sysuser):
|
||||
"""Creates a pop3/imap account for given domain and system user"""
|
||||
"addpopuser sysusrp<num>"
|
||||
|
||||
def readaliasfile(domainname):
|
||||
"""reads the aliasfile for the given domain and returns a dictionary
|
||||
object with the aliases
|
||||
"""
|
||||
aliases={}
|
||||
if (os.access(VIRTUALDOMDIR, os.R_OK)):
|
||||
try:
|
||||
aliasfile=open(VIRTUALDOMDIR+domainname, 'r')
|
||||
for line in aliasfile.readlines():
|
||||
keyvals = string.split(line,":",1)
|
||||
aliases[keyvals[0]]=keyvals[1].strip()
|
||||
aliasfile.close()
|
||||
except IOError:
|
||||
print "couldn't read the aliasfile for "+domainname+"."
|
||||
else:
|
||||
print "couldn't read from "+VIRTUALDOMDIR+"."
|
||||
return aliases
|
||||
|
||||
def writealiasfile(domainname, aliases):
|
||||
"""writes the aliasfile for the given domain with the aliases defined
|
||||
in the dictionary object aliases
|
||||
"""
|
||||
if (os.access(VIRTUALDOMDIR, os.W_OK)):
|
||||
try:
|
||||
aliasfile=open(VIRTUALDOMDIR+domainname, 'w')
|
||||
for key in aliases.keys():
|
||||
aliasfile.write(key+":"+aliases[key]+"\n")
|
||||
aliasfile.close()
|
||||
except IOError:
|
||||
print "writing to aliasfile failed."
|
||||
else:
|
||||
print "no write access to directory "+VIRTUALDOMDIR+"."
|
||||
|
||||
def setmailalias(domainname, alias, target):
|
||||
"""sets a mail alias for given domain which directs the MTA to the
|
||||
given target
|
||||
"""
|
||||
aliases=readaliasfile(domainname)
|
||||
aliases[alias]=target
|
||||
writealiasfile(domainname, aliases)
|
||||
|
||||
createpopaccount("test.de", "usr03")
|
||||
setmailalias("test.de", "doedel", "horst@dittberner.info")
|
|
@ -1,15 +0,0 @@
|
|||
#
|
||||
# Domain manager class for gnuviech-admin tool backend
|
||||
# (c) 2006 Jan Dittberner <jan@dittberner.info>
|
||||
# $Id$
|
||||
#
|
||||
from SessionManager import Session
|
||||
|
||||
class DomainManager:
|
||||
def __init__(self, dbconn):
|
||||
self._dbconn = dbconn
|
||||
|
||||
def listDomains(self, session):
|
||||
if isinstance(session, Session):
|
||||
return 'a,b,c'
|
||||
return ''
|
|
@ -1,62 +0,0 @@
|
|||
#
|
||||
# Service facade for gnuviech-admin tool backend
|
||||
# (c) 2006 Jan Dittberner <jan@dittberner.info>
|
||||
# $Id$
|
||||
#
|
||||
from SessionManager import *
|
||||
from DomainManager import *
|
||||
import Settings
|
||||
import psycopg2
|
||||
|
||||
class ServiceFacade:
|
||||
"""
|
||||
This class implements the facade to the services provided by the
|
||||
gnuviech admin backend.
|
||||
"""
|
||||
def __init__(self):
|
||||
connstr = 'host=%(dbhost)s user=%(dbuser)s ' + \
|
||||
'password=%(dbpassword)s dbname=%(dbname)s'
|
||||
dbconn = psycopg2.connect(connstr % Settings.DBSETTINGS)
|
||||
self.sessionManager = SessionManager(dbconn)
|
||||
self.domainManager = DomainManager(dbconn)
|
||||
|
||||
def _dispatch(self, method, params):
|
||||
try:
|
||||
func = getattr(self, method)
|
||||
except AttributeError:
|
||||
raise Exception('method "%s" is not supported' % method)
|
||||
else:
|
||||
if method != 'login' and method != 'logout':
|
||||
sessionid = params[0]
|
||||
try:
|
||||
session = self.sessionManager.getSession(sessionid)
|
||||
except InvalidSessionError:
|
||||
return ""
|
||||
nparams = [session]
|
||||
for item in params[1:]:
|
||||
nparams.append(item)
|
||||
params = nparams
|
||||
self.sessionManager.updateSession(sessionid)
|
||||
return func(*params)
|
||||
|
||||
def login(self, login, password):
|
||||
"""
|
||||
Logs in the user specified by the given login and password.
|
||||
The method creates a session and returns the session id which
|
||||
has to be sent back by subsequent requests. If the login is
|
||||
invalid the returned id is 0
|
||||
"""
|
||||
try:
|
||||
return self.sessionManager.newSession(login, password)
|
||||
except InvalidLoginError, ile:
|
||||
return 0
|
||||
|
||||
def logout(self, sessionid):
|
||||
self.sessionManager.deleteSession(sessionid)
|
||||
return 0
|
||||
|
||||
def listdomains(self, session):
|
||||
"""
|
||||
Lists the domains the given session may see.
|
||||
"""
|
||||
return self.domainManager.listDomains(session)
|
|
@ -1,95 +0,0 @@
|
|||
"""
|
||||
Session manager class for gnuviech-admin tool backend
|
||||
(c) 2006 Jan Dittberner <jan@dittberner.info>
|
||||
$Id$
|
||||
"""
|
||||
import Settings
|
||||
import os, sha, time, logging, psycopg2
|
||||
from threading import Timer
|
||||
|
||||
SESSIONTIMEOUT=120 # 2 minutes
|
||||
|
||||
class InvalidLoginError(Exception):
|
||||
"""
|
||||
Exception class for invalid logins.
|
||||
"""
|
||||
pass
|
||||
|
||||
class InvalidSessionError(Exception):
|
||||
"""
|
||||
Exception class for invalid sessions.
|
||||
"""
|
||||
pass
|
||||
|
||||
class Session:
|
||||
def __init__(self, id, login):
|
||||
self.id = id
|
||||
self.login = login
|
||||
self._timeoutTimer = None
|
||||
|
||||
def settimeoutTimer(self, timeoutTimer):
|
||||
self._timeoutTimer = timeoutTimer
|
||||
self._timeoutTimer.start()
|
||||
|
||||
def gettimeoutTimer(self):
|
||||
return self._timeoutTimer
|
||||
|
||||
class SessionManager:
|
||||
"""
|
||||
The Sessionmanager provides methods for login and session handling.
|
||||
"""
|
||||
def __init__(self, dbconn):
|
||||
self._sessions = {}
|
||||
self._dbconn = dbconn
|
||||
self._hashobj = sha.new(str(time.time()))
|
||||
self.logger = logging.getLogger('SessionManager')
|
||||
|
||||
def listSessions(self):
|
||||
return self._sessions.keys()
|
||||
|
||||
def newSession(self, login, password):
|
||||
cr = self._dbconn.cursor()
|
||||
cr.execute('SELECT * FROM sysuser WHERE name=%(login)s AND md5pass=md5(%(password)s)' %
|
||||
{'login': psycopg2.QuotedString(login),
|
||||
'password' : psycopg2.QuotedString(password)})
|
||||
self._dbconn.commit()
|
||||
result = cr.fetchall()
|
||||
if cr.rowcount == 1:
|
||||
self._hashobj.update("%s,%s" % (time.time(), login))
|
||||
sessionid = self._hashobj.hexdigest()
|
||||
self._sessions[sessionid] = Session(sessionid, login)
|
||||
self.updateSession(sessionid)
|
||||
self.logger.info('New session with id %s created for %s' %
|
||||
(sessionid, login))
|
||||
return sessionid
|
||||
self.logger.info('Login for %s failed' % login)
|
||||
raise InvalidLoginError
|
||||
|
||||
def updateSession(self, sessionid):
|
||||
self.logger.debug("update session %s" % sessionid)
|
||||
try:
|
||||
session = self.getSession(sessionid)
|
||||
except InvalidSessionError, ev:
|
||||
pass
|
||||
else:
|
||||
if session.gettimeoutTimer() is not None:
|
||||
session.gettimeoutTimer().cancel()
|
||||
session.settimeoutTimer(Timer(SESSIONTIMEOUT, self.deleteSession,
|
||||
args=[sessionid]))
|
||||
|
||||
def getSession(self, sessionid):
|
||||
if self._sessions.has_key(sessionid):
|
||||
return self._sessions[sessionid]
|
||||
raise InvalidSessionError()
|
||||
|
||||
def deleteSession(self, sessionid):
|
||||
self.logger.debug("delete session %s" % sessionid)
|
||||
try:
|
||||
session = self.getSession(sessionid)
|
||||
except InvalidSessionError:
|
||||
print "invalid session"
|
||||
else:
|
||||
if session.gettimeoutTimer() is not None:
|
||||
session.gettimeoutTimer().cancel()
|
||||
del(self._sessions[sessionid])
|
||||
self.logger.debug("%d sessions remaining" % len(self.listSessions()))
|
|
@ -1,25 +0,0 @@
|
|||
#
|
||||
# Settings for gnuviech-admin tool backend
|
||||
# (c) 2006 Jan Dittberner <jan@dittberner.info>
|
||||
# $Id:Settings.py 847 2006-02-21 21:21:30Z jan $
|
||||
#
|
||||
ALLPREFIX = '/home/jan/gnvadmtest'
|
||||
|
||||
DBSETTINGS = { 'dbhost' : 'localhost',
|
||||
'dbuser' : 'gnuviech',
|
||||
'dbpassword' : 'SIKKnsyXsV5yU',
|
||||
'dbname' : 'gnuviechadmin' }
|
||||
# exim:CotOgigmeIk5
|
||||
# courier:jevhi3Wriav
|
||||
# gnuviech:SIKKnsyXsV5yU
|
||||
|
||||
RPCSERVERADDRESS = ('localhost', 8080)
|
||||
|
||||
MAIL_SENDER = 'root@gnuviech.info'
|
||||
MAIL_RECEIVER = 'root@gnuviech.info'
|
||||
POPGROUP = 'poponly'
|
||||
POPHOME = ALLPREFIX + '/home/mail/'
|
||||
WEBHOME = ALLPREFIX + '/home/www/'
|
||||
USERPREFIX = 'usr'
|
||||
|
||||
GNUVIECHADMINDIR = ALLPREFIX + '/var/lib/gnuviechadmin'
|
|
@ -1,9 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# (c) 2006 Jan Dittberner <jan@dittberner.info>
|
||||
# $Id$
|
||||
#
|
||||
"""
|
||||
This package contains classes for the gnuviech administration tool backend.
|
||||
"""
|
||||
from ServiceFacade import *
|
|
@ -1,55 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# (c) 2006 Jan Dittberner <jan@dittberner.info>
|
||||
# $Id$
|
||||
#
|
||||
import psycopg
|
||||
import getopt
|
||||
import sys
|
||||
from gvadm import PasswordTools, DomainTools
|
||||
|
||||
def usage():
|
||||
print """Usage information:
|
||||
=====================
|
||||
%(process)s -h|--help
|
||||
- prints this help text
|
||||
|
||||
%(process)s --domain=<domain> [--password=<password>]
|
||||
- adds a new pop user for the given domain
|
||||
- if the optional password is ommitted a generated one is used
|
||||
- the password is checked using cracklib
|
||||
- if the password is too weak a generated one is used
|
||||
""" % {'process': sys.argv[0]}
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
options = getopt.getopt(sys.argv[1:], "h", ['help', 'password=', 'domain='])
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
if (not options[0] or
|
||||
dict(options[0]).has_key('-h') or
|
||||
dict(options[0]).has_key('--help') or
|
||||
not dict(options[0]).has_key('--domain') or
|
||||
not dict(options[0])['--domain'].strip()):
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
# specify the domain
|
||||
domain = None
|
||||
try:
|
||||
domain = DomainTools.Domain(dict(options[0])['--domain'])
|
||||
except DomainTools.InvalidDomain, iv:
|
||||
print iv
|
||||
sys.exit(1)
|
||||
|
||||
# specify the password
|
||||
password = None
|
||||
|
||||
if dict(options[0]).has_key('--password'):
|
||||
password = PasswordTools.check_password(dict(options[0])['--password'])
|
||||
if (password == None):
|
||||
password = PasswordTools.generate_password()
|
||||
|
||||
domain.makePopUser(password)
|
|
@ -1,59 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import psycopg, getopt, sys
|
||||
|
||||
from gvadm import PasswordTools, DomainTools
|
||||
|
||||
def usage():
|
||||
print """Usage information:
|
||||
=====================
|
||||
%(process)s -h|--help
|
||||
- prints this help text
|
||||
|
||||
%(process)s --domain=<domain> --user=<user> [--password=<password>]
|
||||
- updates the password of a pop user for the given domain
|
||||
- if the optional password is ommitted a generated one is used
|
||||
- the password is checked using cracklib
|
||||
- if the password is too weak a generated one is used
|
||||
""" % {'process': sys.argv[0]}
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
options = getopt.getopt(sys.argv[1:], "h", ['help', 'password=',
|
||||
'domain=', 'user='])
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
if (not options[0] or
|
||||
dict(options[0]).has_key('-h') or
|
||||
dict(options[0]).has_key('--help') or
|
||||
not dict(options[0]).has_key('--domain') or
|
||||
not dict(options[0])['--domain'].strip() or
|
||||
not dict(options[0]).has_key('--user') or
|
||||
not dict(options[0])['--user'].strip()):
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
# specify the domain
|
||||
domain = None
|
||||
try:
|
||||
domain = DomainTools.Domain(dict(options[0])['--domain'])
|
||||
except DomainTools.InvalidDomain, iv:
|
||||
print iv
|
||||
sys.exit(1)
|
||||
|
||||
username = dict(options[0])['--user']
|
||||
if not domain.hasPopUser(username):
|
||||
print "Domain doesn't have pop user", username
|
||||
sys.exit(1)
|
||||
|
||||
# specify the password
|
||||
password = None
|
||||
|
||||
if dict(options[0]).has_key('--password'):
|
||||
password = PasswordTools.check_password(dict(options[0])['--password'])
|
||||
if (password == None):
|
||||
password = PasswordTools.generate_password()
|
||||
|
||||
domain.updatePopPassword(username, password)
|
|
@ -1,177 +0,0 @@
|
|||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
SET client_encoding = 'UNICODE';
|
||||
SET check_function_bodies = false;
|
||||
|
||||
SET SESSION AUTHORIZATION 'postgres';
|
||||
|
||||
BEGIN;
|
||||
|
||||
--
|
||||
-- Name: public; Type: ACL; Schema: -; Owner: postgres
|
||||
--
|
||||
|
||||
REVOKE ALL ON SCHEMA public FROM PUBLIC;
|
||||
GRANT ALL ON SCHEMA public TO PUBLIC;
|
||||
|
||||
SET SESSION AUTHORIZATION 'gnuviech';
|
||||
|
||||
SET search_path = public, pg_catalog;
|
||||
|
||||
--
|
||||
-- Name: country; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
CREATE TABLE country (
|
||||
countryid serial PRIMARY KEY,
|
||||
name character varying(40) NOT NULL
|
||||
);
|
||||
|
||||
REVOKE ALL ON TABLE country FROM PUBLIC;
|
||||
|
||||
--
|
||||
-- Name: reseller; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE reseller (
|
||||
resellerid serial PRIMARY KEY,
|
||||
name character varying(40) NOT NULL
|
||||
);
|
||||
|
||||
REVOKE ALL ON TABLE reseller FROM PUBLIC;
|
||||
|
||||
--
|
||||
-- Name: client; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE client (
|
||||
clientid serial PRIMARY KEY,
|
||||
firstname character varying(40) NOT NULL,
|
||||
lastname character varying(40) NOT NULL,
|
||||
address1 character varying(40) NOT NULL,
|
||||
address2 character varying(40),
|
||||
countryid integer NOT NULL REFERENCES country(countryid),
|
||||
town character varying(50) NOT NULL,
|
||||
zipcode character(5) NOT NULL,
|
||||
state character varying(40),
|
||||
active boolean DEFAULT false NOT NULL,
|
||||
phone character varying(20),
|
||||
mobile character varying(20),
|
||||
reseller_id integer REFERENCES reseller(resellerid),
|
||||
organisation character varying(200)
|
||||
);
|
||||
|
||||
REVOKE ALL ON TABLE client FROM PUBLIC;
|
||||
|
||||
--
|
||||
-- Name: email; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE email (
|
||||
emailid serial PRIMARY KEY,
|
||||
email character varying(128) NOT NULL,
|
||||
clientid integer NOT NULL REFERENCES client(clientid),
|
||||
verified boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
REVOKE ALL ON TABLE email FROM PUBLIC;
|
||||
|
||||
--
|
||||
-- Name: sysuser; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE sysuser (
|
||||
sysuserid serial PRIMARY KEY,
|
||||
name character varying(12) NOT NULL,
|
||||
"type" integer DEFAULT 0 NOT NULL,
|
||||
home character varying(128),
|
||||
shell boolean,
|
||||
"password" character varying(64),
|
||||
clientid integer NOT NULL REFERENCES client(clientid),
|
||||
toupdate boolean DEFAULT false NOT NULL,
|
||||
md5pass character varying(32),
|
||||
sysuid integer UNIQUE
|
||||
);
|
||||
|
||||
REVOKE ALL ON TABLE sysuser FROM PUBLIC;
|
||||
GRANT SELECT ON TABLE sysuser TO GROUP services;
|
||||
|
||||
--
|
||||
-- Name: domain; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE "domain" (
|
||||
domainid serial PRIMARY KEY,
|
||||
domainname character varying(64) NOT NULL,
|
||||
clientid integer NOT NULL REFERENCES client(clientid),
|
||||
status integer DEFAULT 0 NOT NULL,
|
||||
sysuserid integer NOT NULL REFERENCES sysuser(sysuserid)
|
||||
);
|
||||
|
||||
REVOKE ALL ON TABLE "domain" FROM PUBLIC;
|
||||
GRANT SELECT ON TABLE "domain" TO GROUP services;
|
||||
|
||||
--
|
||||
-- Name: zone; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE "zone" (
|
||||
zoneid serial PRIMARY KEY,
|
||||
"domain" integer NOT NULL REFERENCES domain(domainid),
|
||||
"type" character varying(5) NOT NULL,
|
||||
ttl integer NOT NULL,
|
||||
mxprio integer,
|
||||
resource character varying(256),
|
||||
toupdate boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
REVOKE ALL ON TABLE "zone" FROM PUBLIC;
|
||||
|
||||
--
|
||||
-- Name: mailpasswd; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE mailpasswd (
|
||||
id character varying(128) NOT NULL,
|
||||
crypt character varying(128) DEFAULT '' NOT NULL,
|
||||
clear character varying(128) DEFAULT '' NOT NULL,
|
||||
name character varying(128) DEFAULT '' NOT NULL,
|
||||
uid integer DEFAULT 65534 NOT NULL,
|
||||
gid integer DEFAULT 65534 NOT NULL,
|
||||
home character varying(255) DEFAULT '' NOT NULL,
|
||||
maildir character varying(255) DEFAULT '' NOT NULL,
|
||||
defaultdelivery character varying(255) DEFAULT '' NOT NULL,
|
||||
quota character varying(255) DEFAULT '' NOT NULL,
|
||||
spamcheck boolean DEFAULT false NOT NULL,
|
||||
sajunkscore integer
|
||||
);
|
||||
|
||||
REVOKE ALL ON TABLE mailpasswd FROM PUBLIC;
|
||||
GRANT ALL ON TABLE mailpasswd TO GROUP services;
|
||||
|
||||
--
|
||||
-- Name: mailalias; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE mailalias (
|
||||
email character varying(255) NOT NULL,
|
||||
"domain" character varying(255) NOT NULL,
|
||||
target character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
REVOKE ALL ON TABLE mailalias FROM PUBLIC;
|
||||
GRANT ALL ON TABLE mailalias TO GROUP services;
|
||||
|
||||
--
|
||||
-- Name: country; Type: TABLE DATA; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
INSERT INTO country (countryid, name) VALUES (1, 'Deutschland');
|
||||
INSERT INTO country (countryid, name) VALUES (2, 'Schweiz');
|
||||
INSERT INTO country (countryid, name) VALUES (3, 'Österreich');
|
||||
|
||||
SET SESSION AUTHORIZATION 'postgres';
|
||||
|
||||
COMMIT;
|
|
@ -1,128 +0,0 @@
|
|||
"""GNUViech administration tool helper classes.
|
||||
|
||||
(c) 2004 Jan Dittberner <jan@gnuviech.info>
|
||||
"""
|
||||
|
||||
import os
|
||||
from log4py import Logger, FileAppender, LOGLEVEL_DEBUG
|
||||
|
||||
class GNVPrefs:
|
||||
"""This class has static variables for the settings of the GNUViech
|
||||
administration tool. These settings may be customized in the file
|
||||
gvadm.preferences."""
|
||||
# define standard values
|
||||
PWDMINLENGTH = 6
|
||||
PWDMAXLENGTH = 12
|
||||
PWDCHARS = range(ord('a'), ord('z'))
|
||||
PWDCHARS.extend(range(ord('A'), ord('Z')))
|
||||
PWDCHARS.extend(range(ord('0'), ord('9')))
|
||||
PWDCHARS.extend((ord('@'), ord('#'), ord(','), ord('.'), ord('*'),
|
||||
ord('+'), ord('-'), ord('='), ord('!'), ord('$'),
|
||||
ord('"')))
|
||||
USERPREFIX = "usr"
|
||||
BASEPREFIX = ""
|
||||
GVADMDIR = BASEPREFIX+"/etc/gvadm/"
|
||||
EXIMCONFDIR = BASEPREFIX+"/etc/exim/"
|
||||
VIRTUALDOMDIR = EXIMCONFDIR+"virtual/"
|
||||
HOMEDIR = BASEPREFIX+"/home"
|
||||
POPHOMEDIR = HOMEDIR+"/mail/"
|
||||
WEBHOMEDIR = HOMEDIR+"/www/"
|
||||
WEBLOGDIR = WEBHOMEDIR+"logs/"
|
||||
WEBSTATSDIR = WEBHOMEDIR+"stats/"
|
||||
LOGDIR = BASEPREFIX+"/var/log"
|
||||
LOGFILE = LOGDIR+"/gnvadm.log"
|
||||
USERTYPES = {
|
||||
"web" : {
|
||||
"minuid" : 10000,
|
||||
"maxuid" : 10999,
|
||||
"group" : "wwwusers",
|
||||
"fullname" : "Webuser %s",
|
||||
"home" : WEBHOMEDIR + "%s",
|
||||
"shell" : "/bin/true",
|
||||
"nohome" : 1,
|
||||
"disabledpass" : 1
|
||||
},
|
||||
"pop3" : {
|
||||
"minuid" : 20000,
|
||||
"maxuid" : 29999,
|
||||
"group" : "poponly",
|
||||
"fullname" : "Popuser %s",
|
||||
"home" : POPHOMEDIR + "%s",
|
||||
"shell" : "/bin/true",
|
||||
"nohome" : 1,
|
||||
"disabledpass" : 1
|
||||
}
|
||||
}
|
||||
# load custom settings
|
||||
execfile("gvadm.preferences")
|
||||
|
||||
def __init__(self):
|
||||
self.logger = self.getLogger(self)
|
||||
self.setupDirs()
|
||||
|
||||
def __repr__(self):
|
||||
items = dir(self)
|
||||
items.sort()
|
||||
return "gnuviech.GNVPrefs\n\t" + "\n\t".join(["%s = %s" %
|
||||
(item, getattr(self, item)) for item in items if getattr(self, item).__class__ in (str, int, list, dict)]) + "\n"
|
||||
|
||||
def setupDirs(self):
|
||||
"""Setup the directories and files required for proper operation of the
|
||||
GNUViech administration tool."""
|
||||
for directory in (self.BASEPREFIX,
|
||||
self.BASEPREFIX+"/etc",
|
||||
self.BASEPREFIX+"/var",
|
||||
self.GVADMDIR,
|
||||
self.EXIMCONFDIR,
|
||||
self.VIRTUALDOMDIR,
|
||||
self.HOMEDIR,
|
||||
self.POPHOMEDIR,
|
||||
self.WEBHOMEDIR,
|
||||
self.WEBLOGDIR,
|
||||
self.WEBSTATSDIR,
|
||||
self.LOGDIR):
|
||||
if (not os.access(directory, os.R_OK & os.X_OK)):
|
||||
print "making %s." % directory
|
||||
os.mkdir(directory)
|
||||
for required in (self.BASEPREFIX+"/etc/passwd",
|
||||
self.BASEPREFIX+"/etc/shadow",
|
||||
self.EXIMCONFDIR+"eximpasswords"):
|
||||
if (not os.access(required, os.R_OK)):
|
||||
print "creating %s." % required
|
||||
file = open(required, "w")
|
||||
file.close()
|
||||
|
||||
def getLogger(self, instance):
|
||||
logger = Logger().get_instance(instance)
|
||||
logger.remove_all_targets()
|
||||
logger.add_target(FileAppender(self.LOGFILE))
|
||||
logger.set_loglevel(LOGLEVEL_DEBUG)
|
||||
return logger
|
||||
|
||||
def getNextSysId(self, type):
|
||||
nextid = self.USERTYPES[type]["minuid"]
|
||||
file = open(self.BASEPREFIX+"/etc/passwd", "r")
|
||||
for line in file.readlines():
|
||||
pwdline = tools.splitPasswdLine(line)
|
||||
self.logger.debug(str(pwdline))
|
||||
uid = int(pwdline["uid"])
|
||||
if (uid in
|
||||
range(int(self.USERTYPES[type]["minuid"]),
|
||||
int(self.USERTYPES[type]["maxuid"]))
|
||||
and nextid <= uid): nextid = uid+1
|
||||
return nextid
|
||||
|
||||
def getGroupId(self, type): pass
|
||||
|
||||
def getFullName(self, type, username):
|
||||
return self.USERTYPES[type]["fullname"] % username
|
||||
|
||||
def getHomeDir(self, type, username):
|
||||
return self.USERTYPES[type]["home"] % username
|
||||
|
||||
def getShell(self, type):
|
||||
return self.USERTYPES[type]["shell"]
|
||||
|
||||
class NoAdmDirError(Exception):
|
||||
"""This exception is raised if the admin directory does'nt exist."""
|
||||
pass
|
|
@ -1,152 +0,0 @@
|
|||
"""Package for GNUViech Admin main types and functions
|
||||
|
||||
(c) Copyright 2004 Jan Dittberner, IT-Consulting & Solutions
|
||||
Germany
|
||||
"""
|
||||
|
||||
import os, pwd
|
||||
import gnuviech
|
||||
from gnuviech import sysuser
|
||||
|
||||
class DomainNotExistentError(Exception): pass
|
||||
|
||||
class DomainFileNotExistentError(Exception): pass
|
||||
|
||||
class GNVDomain:
|
||||
"""Represents a domain in the GNUViech admin tool"""
|
||||
|
||||
def __init__(self, domain, prefs):
|
||||
"""Initializes the domain object"""
|
||||
self.logger = prefs.getLogger(self)
|
||||
self.prefs = prefs
|
||||
self.name = domain
|
||||
self.webaccount = None
|
||||
self.zone = None
|
||||
self.statsusers = {}
|
||||
self.mailaliases = {}
|
||||
self.pop3accounts = {}
|
||||
try:
|
||||
self.__findUser()
|
||||
except gnuviech.NoAdmDirError:
|
||||
prefs.setupDirs()
|
||||
self.__init__(domain)
|
||||
except DomainFileNotExistentError:
|
||||
self.__createDomainFile()
|
||||
self.__init__(domain, prefs)
|
||||
except DomainNotExistentError:
|
||||
self.__createUser()
|
||||
self.createWebUser()
|
||||
|
||||
def __repr__(self):
|
||||
retval = "Domain "+self.name
|
||||
if not self.username is None:
|
||||
retval += ", User "+self.username
|
||||
else:
|
||||
retval += ", new domain"
|
||||
return retval
|
||||
|
||||
def __createDomainFile(self):
|
||||
"""Create the domain user id map file."""
|
||||
file = open(gnuviech.GNVPrefs.GVADMDIR+"domains", "w")
|
||||
file.close()
|
||||
|
||||
def __createUser(self):
|
||||
"""Create a user for the domain."""
|
||||
file = open(self.prefs.GVADMDIR+"domains", "r")
|
||||
id = 0
|
||||
for line in file.readlines():
|
||||
(key, value) = line.split(":")
|
||||
if (int(value) > id): id = int(value)
|
||||
file.close()
|
||||
id += 1
|
||||
file = open(self.prefs.GVADMDIR+"domains", "a")
|
||||
file.write("%s:%d\n" % (self.name, id))
|
||||
file.close()
|
||||
self.__findUser()
|
||||
|
||||
def __findUser(self):
|
||||
"""Finds the user for the domain."""
|
||||
self.username = None
|
||||
if (os.access(self.prefs.GVADMDIR, os.R_OK)):
|
||||
try:
|
||||
domainsfile = open(self.prefs.GVADMDIR+"domains", "r")
|
||||
for line in domainsfile.readlines():
|
||||
(key, value) = line.split(":")
|
||||
if (key == self.name):
|
||||
self.username = "%s%02d" % (
|
||||
self.prefs.USERPREFIX,
|
||||
int(value))
|
||||
domainsfile.close()
|
||||
if self.username is None:
|
||||
raise DomainNotExistentError
|
||||
except IOError:
|
||||
raise DomainFileNotExistentError
|
||||
else:
|
||||
raise gnuviech.NoAdmDirError
|
||||
|
||||
def getMaxPop3Id(self):
|
||||
maxid = 0
|
||||
try:
|
||||
passwdfile = open(gnuviech.GNVPrefs.BASEPREFIX+"/etc/passwd", "r")
|
||||
for line in passwdfile.readlines():
|
||||
(login, passwd, uid, gid, name, dir, shell) = line.split(":")
|
||||
if login.startswith(self.username + "p"):
|
||||
id = int(login[len(self.username):])
|
||||
print id
|
||||
if (id > maxid): maxid = id
|
||||
except IOError:
|
||||
pass
|
||||
return maxid
|
||||
|
||||
def getNextUser(self, usertype):
|
||||
"""Gets the next user for the given type."""
|
||||
if (usertype == "web"):
|
||||
return self.username
|
||||
if (usertype == "pop3"):
|
||||
return "%sp%d" % (self.username, self.getMaxPop3Id()+1)
|
||||
|
||||
def addPOP3Account(self, account):
|
||||
self.pop3accounts[account.localpart] = account
|
||||
|
||||
def addMailAlias(self, alias):
|
||||
self.mailaliases[alias.localpart] = alias
|
||||
|
||||
def createWebUser(self):
|
||||
try:
|
||||
self.webaccount = sysuser.SystemUser(self.prefs, self.username)
|
||||
except sysuser.UserNotInPasswdError:
|
||||
self.webaccount = sysuser.createUser(self.prefs, self.username,
|
||||
"web")
|
||||
self.logger.debug(str(self.webaccount))
|
||||
|
||||
# #!/bin/sh
|
||||
# . /usr/local/etc/preferences
|
||||
# if [ -n $USERPREFIX ]; then
|
||||
# USERPREFIX="usr"
|
||||
# fi
|
||||
# if [ $1 == "" ]; then
|
||||
# echo "usage: $0 <usernum>"
|
||||
# exit
|
||||
# fi
|
||||
|
||||
# NEWUSER="$USERPREFIX$1"
|
||||
# NEWHOME="/home/www/$NEWUSER"
|
||||
# LOGDIR="/home/www/logfiles/$NEWUSER"
|
||||
|
||||
# adduser --home "$NEWHOME" --shell /bin/true --no-create-home --firstuid 10000 --ingroup wwwusers --disabled-password --gecos "Webuser $NEWUSER" $NEWUSER
|
||||
|
||||
# echo "${NEWUSER}:${NEWPASS}" | chpasswd
|
||||
# mkdir -p "$NEWHOME/"{html,cgi-bin}
|
||||
# mkdir -p "$LOGDIR"
|
||||
# chown -Rc www-data.www-data "$LOGDIR"
|
||||
# chmod 0750 "$LOGDIR"
|
||||
# chown -Rc $NEWUSER.wwwusers "$NEWHOME"
|
||||
# mkdir -p "$NEWHOME/html/stats"
|
||||
# chown modlogan.wwwusers "$NEWHOME/html/stats"
|
||||
# htpasswd -bc "/home/www/${NEWUSER}stats" "${NEWUSER}" "${NEWPASS}"
|
||||
|
||||
# echo added new web user $NEWUSER with password $NEWPASS
|
||||
|
||||
if __name__ == "__main__":
|
||||
dom = GNVDomain("dittberner.info")
|
||||
print dom
|
|
@ -1,62 +0,0 @@
|
|||
from gnuviech import tools
|
||||
|
||||
class UserNotInPasswdError(Exception): pass
|
||||
|
||||
class NoPasswordInShadowError(Exception): pass
|
||||
|
||||
class SystemUser:
|
||||
def __init__(self, prefs, username):
|
||||
self.prefs = prefs
|
||||
self.logger = prefs.getLogger(self)
|
||||
self.getUser(username)
|
||||
self.logger.debug(str(self))
|
||||
|
||||
def getUser(self, username):
|
||||
pwdfile = open(self.prefs.BASEPREFIX+"/etc/passwd", "r")
|
||||
for line in pwdfile.readlines():
|
||||
pwdline = tools.splitPasswdLine(line)
|
||||
self.logger.debug("PWDLINE: %s" % pwdline)
|
||||
if pwdline["loginname"] == username:
|
||||
self.username = pwdline["loginname"]
|
||||
self.password = self.getPassword()
|
||||
self.uid = pwdline["uid"]
|
||||
self.gid = pwdline["gid"]
|
||||
self.fullname = pwdline["fullname"]
|
||||
self.homedir = pwdline["homedir"]
|
||||
self.shell = pwdline["shell"]
|
||||
return
|
||||
pwdfile.close()
|
||||
raise UserNotInPasswdError
|
||||
|
||||
def getPassword(self):
|
||||
shadowfile = open(self.prefs.BASEPREFIX+"/etc/shadow", "r")
|
||||
for line in shadowfile.readlines():
|
||||
shadowline = tools.splitShadowLine(line)
|
||||
self.logger.debug("SHADOWLINE: %s" % shadowline)
|
||||
if shadowline["loginname"] == self.username:
|
||||
shadowfile.close()
|
||||
return shadowline["passwordhash"]
|
||||
shadowfile.close()
|
||||
raise NoPasswordInShadowError
|
||||
|
||||
def createUser(prefs, username, type):
|
||||
line = ":".join((username, "x",
|
||||
str(prefs.getNextSysId(type)),
|
||||
str(prefs.getGroupId(type)),
|
||||
prefs.getFullName(type, username),
|
||||
prefs.getHomeDir(type, username),
|
||||
prefs.getShell(type)))
|
||||
passwdfile = open(prefs.BASEPREFIX+"/etc/passwd", "a")
|
||||
passwdfile.write("%s\n" % line)
|
||||
passwdfile.close()
|
||||
createShadowItem(prefs, username, type, tools.generatePassword())
|
||||
return SystemUser(prefs, username)
|
||||
|
||||
def createShadowItem(prefs, username, type, password):
|
||||
line = ":".join((username,
|
||||
tools.hashPassword(password, "md5"),
|
||||
str(tools.daysSince1970()),
|
||||
"0", "99999", "7", "", "", ""))
|
||||
shadowfile = open(prefs.BASEPREFIX+"/etc/shadow", "a")
|
||||
shadowfile.write("%s\n" % line)
|
||||
shadowfile.close()
|
|
@ -1,71 +0,0 @@
|
|||
"""Tool functions for GNUViech administration tool
|
||||
|
||||
(c) 2004 Jan Dittberner <jan@gnuviech.info>
|
||||
"""
|
||||
|
||||
import random, re
|
||||
from gnuviech import GNVPrefs
|
||||
try:
|
||||
from crypt import crypt
|
||||
except ImportError, ie:
|
||||
import sys
|
||||
sys.__stderr__.write("Unsupported platform without crypt: " + sys.platform)
|
||||
sys.exit()
|
||||
from time import time
|
||||
|
||||
def generatePassword():
|
||||
"""Generates a password from the chars in GNVPrefs.PWDCHARS with
|
||||
a length between GNVPrefs.PWDMINLENGTH and GNVPrefs.PWDMAXLENGTH."""
|
||||
return "".join([chr(char) for char in
|
||||
random.sample(GNVPrefs.PWDCHARS,
|
||||
random.randint(GNVPrefs.PWDMINLENGTH,
|
||||
GNVPrefs.PWDMAXLENGTH))])
|
||||
|
||||
def generateSalt():
|
||||
saltchars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
salt = []
|
||||
for i in range(8):
|
||||
salt.append(saltchars[random.randint(0, len(saltchars) - 1)])
|
||||
return "".join(salt)
|
||||
|
||||
def checkEmail(email):
|
||||
"""Returns a match object if the given email address is syntactically
|
||||
correct otherwise it returns None"""
|
||||
# regex for email check
|
||||
p = re.compile(r'^([a-zA-Z0-9_\-.]+)@([a-zA-Z0-9\-]+(\.|[a-zA-Z0-9\-]+)*\.[a-z]{2,5})$')
|
||||
return p.search(email)
|
||||
|
||||
def splitPasswdLine(line):
|
||||
loginname, password, uid, gid, fullname, directory, shell = line.split(":")
|
||||
return {
|
||||
"loginname" : loginname,
|
||||
"password" : password,
|
||||
"uid" : uid,
|
||||
"gid" : gid,
|
||||
"fullname" : fullname,
|
||||
"homedir" : directory,
|
||||
"shell" : shell
|
||||
}
|
||||
|
||||
def splitShadowLine(line):
|
||||
(loginname, passwordhash, lastchange, maychange, mustchange, warnexpire,
|
||||
disabled, disabledsince, reserved) = line.split(":")
|
||||
return {
|
||||
"loginname" : loginname,
|
||||
"passwordhash" : passwordhash,
|
||||
"lastchange" : lastchange,
|
||||
"maychange" : maychange,
|
||||
"mustchange" : mustchange,
|
||||
"warnexpire" : warnexpire,
|
||||
"disabled" : disabled,
|
||||
"disabledsince" : disabledsince,
|
||||
"reserved" : reserved
|
||||
}
|
||||
|
||||
def hashPassword(password, method="md5"):
|
||||
if (method == "md5"):
|
||||
return crypt(password, "$1$%s" % generateSalt())
|
||||
return crypt(password, generateSalt())
|
||||
|
||||
def daysSince1970():
|
||||
return int(time()/(3600*24))
|
|
@ -1,12 +0,0 @@
|
|||
USERPREFIX = "usr"
|
||||
BASEPREFIX = "../tmp"
|
||||
GVADMDIR = BASEPREFIX+"/etc/gvadm/"
|
||||
EXIMCONFDIR = BASEPREFIX+"/etc/exim4/"
|
||||
VIRTUALDOMDIR = EXIMCONFDIR+"virtual/"
|
||||
HOMEDIR = BASEPREFIX+"/home"
|
||||
POPHOMEDIR = HOMEDIR+"/mail/"
|
||||
WEBHOMEDIR = HOMEDIR+"/www/"
|
||||
WEBLOGDIR = WEBHOMEDIR+"logs/"
|
||||
WEBSTATSDIR = WEBHOMEDIR+"stats/"
|
||||
LOGDIR = BASEPREFIX+"/var/log"
|
||||
LOGFILE = LOGDIR+"/gnvadm.log"
|
|
@ -1,175 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import psycopg, pwd, grp, smtplib, os
|
||||
from email.MIMEText import MIMEText
|
||||
import Settings, PasswordTools
|
||||
|
||||
class InvalidDomain(Exception):
|
||||
"""This exception is raised if an invalid domain is used."""
|
||||
def __init__(self, domain):
|
||||
self.domain = domain
|
||||
|
||||
def __str__(self):
|
||||
return repr("Invalid domain %s" % (self.domain))
|
||||
|
||||
class NoSysuserForDomain(Exception):
|
||||
"""This exception is raised if no system user is associated with a domain."""
|
||||
def __init__(self, domain):
|
||||
self.domain = domain
|
||||
|
||||
def __str__(self):
|
||||
return repr("No system user for domain %s" % (self.domain))
|
||||
|
||||
class InvalidPopUser(Exception):
|
||||
"""This exception is raised if an invalid POP3/IMAP user has been specified."""
|
||||
def __init__(self, domain, username):
|
||||
self.domain = domain
|
||||
self.username = username
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid POP3/IMAP user %s in domain %s." % (self.username, self.domain)
|
||||
|
||||
class Domain:
|
||||
"""A Domain representation object with service methods."""
|
||||
def __init__(self, domain):
|
||||
self.cnx = psycopg.connect("user=%(dbuser)s password=%(dbpassword)s dbname=%(dbname)s" % Settings.dbsettings)
|
||||
self.domain = domain
|
||||
self.validate_domain()
|
||||
|
||||
def validate_domain(self):
|
||||
"""This function validates whether the given domain is allowed.
|
||||
That means that the domain needs to be registered in the database.
|
||||
|
||||
If the domain is invalid InvalidDomain is raised."""
|
||||
cr = self.cnx.cursor()
|
||||
|
||||
cr.execute("SELECT * FROM domain WHERE domainname=%(name)s" %
|
||||
{'name': psycopg.QuotedString(self.domain)})
|
||||
self.cnx.commit()
|
||||
|
||||
result = cr.fetchall()
|
||||
if (not result):
|
||||
raise InvalidDomain(self)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.domain)
|
||||
|
||||
def getSysuser(self):
|
||||
"""Gets the system user id of the domain."""
|
||||
cr = self.cnx.cursor()
|
||||
|
||||
cr.execute("""SELECT sysuser.name FROM domain, sysuser
|
||||
WHERE domain.domainname=%(name)s
|
||||
AND domain.sysuserid=sysuser.sysuserid""" %
|
||||
{'name': psycopg.QuotedString(self.domain)})
|
||||
self.cnx.commit()
|
||||
|
||||
result = cr.fetchall()
|
||||
if (not result):
|
||||
raise NoSysuserForDomain(self)
|
||||
# return row 0, field 0
|
||||
return result[0][0]
|
||||
|
||||
def getNextPopUser(self):
|
||||
"""Gets the user id of the next available POP3/IMAP-user for the domain."""
|
||||
cr = self.cnx.cursor()
|
||||
|
||||
sysuser = self.getSysuser()
|
||||
|
||||
cr.execute("""SELECT max(id) FROM mailpasswd WHERE
|
||||
id LIKE %(username)s""" %
|
||||
{'username': psycopg.QuotedString(sysuser+'%')})
|
||||
self.cnx.commit()
|
||||
|
||||
result = cr.fetchall()
|
||||
if (not result):
|
||||
return sysuser + "p1"
|
||||
|
||||
maxpopuser = result[0][0]
|
||||
if (not maxpopuser):
|
||||
return sysuser + "p1"
|
||||
|
||||
num = int(maxpopuser[len(sysuser)+1:])+1
|
||||
return "%sp%d" % (sysuser, num)
|
||||
|
||||
def makePopUser(self, password):
|
||||
"""Creates a new POP3/IMAP-user for the domain using the given password."""
|
||||
cr = self.cnx.cursor()
|
||||
|
||||
sysuser = self.getSysuser()
|
||||
popaccount = self.getNextPopUser()
|
||||
crypted = PasswordTools.md5_crypt_password(password)
|
||||
uid = pwd.getpwnam(sysuser)[2]
|
||||
gid = grp.getgrnam(Settings.popgroup)[2]
|
||||
homedir = Settings.pophome + popaccount
|
||||
|
||||
os.mkdir(homedir, 0755)
|
||||
os.system("maildirmake \"%s/Maildir\"" % (homedir))
|
||||
os.system("chown -R %s.%s %s" % ( sysuser, Settings.popgroup, homedir ))
|
||||
|
||||
cr = self.cnx.cursor()
|
||||
cr.execute("""INSERT INTO mailpasswd (id, crypt, clear, uid, gid, home)
|
||||
VALUES (%(id)s, %(crypt)s, %(clear)s, %(uid)d, %(gid)d, %(home)s)""" % {
|
||||
'id': psycopg.QuotedString(popaccount),
|
||||
'crypt': psycopg.QuotedString(crypted),
|
||||
'clear': psycopg.QuotedString(password),
|
||||
'uid': uid, 'gid': gid,
|
||||
'home': psycopg.QuotedString(homedir)})
|
||||
self.cnx.commit()
|
||||
|
||||
text = """A new POP3/IMAP account has been created
|
||||
Domain: %(domain)s
|
||||
User: %(user)s
|
||||
Password: %(password)s""" % {'domain': self.domain,
|
||||
'user': popaccount,
|
||||
'password': password}
|
||||
themail = MIMEText(text)
|
||||
themail['Subject'] = "A new POP3/IMAP account has been created"
|
||||
themail['From'] = Settings.mailsender
|
||||
themail['To'] = Settings.mailreceiver
|
||||
|
||||
s = smtplib.SMTP()
|
||||
s.connect()
|
||||
s.sendmail(Settings.mailsender, [Settings.mailreceiver], themail.as_string())
|
||||
s.close()
|
||||
|
||||
def listPopUsers(self):
|
||||
sysuser = self.getSysuser()
|
||||
|
||||
cr = self.cnx.cursor()
|
||||
cr.execute("SELECT id FROM mailpasswd WHERE id LIKE %(user)s" % {
|
||||
'user': psycopg.QuotedString(sysuser + '%')})
|
||||
self.cnx.commit()
|
||||
|
||||
result = cr.fetchall()
|
||||
return [line[0] for line in result]
|
||||
|
||||
def hasPopUser(self, username):
|
||||
"""Checks whether the specified POP3/IMAP user exists in the domain."""
|
||||
return ([user for user in self.listPopUsers() if (user == username)])
|
||||
|
||||
def updatePopPassword(self, username, password=PasswordTools.generate_password()):
|
||||
"""Updates the password of the given POP3/IMAP user."""
|
||||
if self.hasPopUser(username):
|
||||
crypted = PasswordTools.md5_crypt_password(password)
|
||||
|
||||
cr = self.cnx.cursor()
|
||||
cr.execute("UPDATE mailpasswd SET clear=%(clear)s, crypt=%(crypt)s WHERE id=%(user)s" % {
|
||||
'clear': psycopg.QuotedString(password),
|
||||
'crypt': psycopg.QuotedString(crypted),
|
||||
'user': psycopg.QuotedString(username)})
|
||||
self.cnx.commit()
|
||||
print("updated password of user %s to %s" % (username, password))
|
||||
else:
|
||||
raise InvalidPopUser(self, username)
|
||||
|
||||
if __name__ == '__main__':
|
||||
domain = Domain('centrum-warenhaus-dresden.de')
|
||||
# list pop users
|
||||
print ", ".join(domain.listPopUsers())
|
||||
# check for not existing user
|
||||
#try:
|
||||
# domain.updatePopPassword('usr03p2', 'test')
|
||||
#except InvalidPopUser, ipu:
|
||||
# print ipu
|
||||
#domain.updatePopPassword('usr05p2')
|
|
@ -1,25 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import crypt, crack, popen2, random
|
||||
|
||||
def generate_password():
|
||||
(o, i, e) = popen2.popen3("apg -n 1 -m 8 -x 12 -a 0")
|
||||
|
||||
return "".join(o.readlines()).strip()
|
||||
|
||||
def check_password(password):
|
||||
try:
|
||||
return crack.VeryFascistCheck(password)
|
||||
except ValueError, ve:
|
||||
print "Weak password:", ve
|
||||
return None
|
||||
|
||||
def md5_crypt_password(password):
|
||||
salt = "".join([chr(letter) for letter in random.sample(range(ord('a'), ord('z')), 8)])
|
||||
|
||||
return crypt.crypt(password, '$1$' + salt)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print check_password("test")
|
||||
print generate_password()
|
||||
print md5_crypt_password("test")
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""This package contains classes for the gnuviech administration tool
|
||||
backend."""
|
||||
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import os, string
|
||||
import gnuviech
|
||||
#from GNVAdm import GNVDomain
|
||||
from gnuviech import GNVPrefs, tools
|
||||
from gnuviech.gnvdomain import GNVDomain
|
||||
|
||||
# if [ -n $USERPREFIX ]; then
|
||||
# USERPREFIX="usr"
|
||||
# fi
|
||||
|
||||
# if [ $1 == "" ]; then
|
||||
# echo "give <UserNumber>p<pop3Account> as parameter"
|
||||
# exit
|
||||
# fi
|
||||
|
||||
# NEWUSER="$USERPREFIX$1"
|
||||
# NEWHOME="/home/mail/$NEWUSER"
|
||||
# NEWPASS=$(apg -n 1 -a 1 -CL -m 8 -x 12)
|
||||
# echo $NEWHOME
|
||||
|
||||
# adduser --home "$NEWHOME" --shell /bin/true --no-create-home --firstuid 20000 --ingroup poponly --disabled-password --disabled-login --gecos "Popuser $NEWUSER" $NEWUSER
|
||||
|
||||
# mkdir -p "$NEWHOME"
|
||||
# chown -Rc $NEWUSER.poponly "$NEWHOME"
|
||||
# echo "${NEWUSER}:${NEWPASS}" | chpasswd
|
||||
|
||||
# echo "Herzlich willkommen auf dem GNU-Viech" | mail -s "Willkommen auf dem GNU-Viech" ${NEWUSER}
|
||||
# echo added new pop3 user $NEWUSER with password $NEWPASS
|
||||
|
||||
class MailAliasExists(Exception): pass
|
||||
|
||||
class POP3AccountExists(Exception): pass
|
||||
|
||||
class MailAccount:
|
||||
def __init__(self, domain, localpart):
|
||||
"Initialize a MailAccount instance for a given domain"
|
||||
if (not os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.R_OK & os.X_OK)):
|
||||
self.setupDirs()
|
||||
self.domain = domain
|
||||
self.localpart = localpart
|
||||
self.prefs = domain.prefs
|
||||
self.logger = domain.prefs.getLogger(self)
|
||||
|
||||
def __repr__(self):
|
||||
return "%s@%s" % (self.localpart, self.domain.name)
|
||||
|
||||
class MailAlias(MailAccount):
|
||||
"""This represents a mail alias"""
|
||||
|
||||
def __init__(self, domain, localpart, target):
|
||||
"Initialize the POPAccount class for a given domain"
|
||||
if localpart in domain.mailaliases.keys():
|
||||
raise MailAliasExists
|
||||
MailAccount.__init__(self, domain, localpart)
|
||||
self.setTarget(target)
|
||||
|
||||
def setTarget(self, target):
|
||||
self.target = target
|
||||
self.logger.debug("setting target for alias %s to %s." %
|
||||
(str(self), self.target))
|
||||
# self.aliases = {}
|
||||
# self.readAll()
|
||||
|
||||
# def readAll():
|
||||
# """reads the aliasfile for the given domain"""
|
||||
# self.aliases = {}
|
||||
# if (os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.R_OK)):
|
||||
# try:
|
||||
# aliasfile = open(gnuviech.GNVPrefs.VIRTUALDOMDIR+self.domain.name , 'r')
|
||||
# for line in aliasfile.readlines():
|
||||
# keyvals = string.split(line,":",1)
|
||||
# self.aliases[keyvals[0]] = keyvals[1].strip()
|
||||
# aliasfile.close()
|
||||
# except IOError:
|
||||
# self.logger.error("couldn't read the aliasfile for "+self.domain.name+".")
|
||||
# else:
|
||||
# self.logger.error("couldn't read from "+gnuviech.GNVPrefs.VIRTUALDOMDIR+".")
|
||||
|
||||
# def writeAll(self):
|
||||
# """writes the aliasfile for the given domain with the aliases defined
|
||||
# in the dictionary object aliases"""
|
||||
# if (os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.W_OK)):
|
||||
# try:
|
||||
# aliasfile = open(gnuviech.GNVPrefs.VIRTUALDOMDIR+self.domain.name, 'w')
|
||||
# keys = self.aliases.keys();
|
||||
# keys.sort();
|
||||
# for key in keys:
|
||||
# aliasfile.write("%s:%s" % (key, self.aliases[key]) + "\n")
|
||||
# aliasfile.close()
|
||||
# except IOError:
|
||||
# self.logger.error("writing to aliasfile failed.")
|
||||
# else:
|
||||
# self.logger.error("no write access to directory "+gnuviech.GNVPrefs.VIRTUALDOMDIR+".")
|
||||
|
||||
# def setAlias(self, alias, target):
|
||||
# """sets a mail alias for given domain which directs the MTA to the
|
||||
# given target
|
||||
# """
|
||||
# self.readAll()
|
||||
# self.aliases[alias]=target
|
||||
# self.writeAll()
|
||||
|
||||
class POP3Account(MailAccount):
|
||||
"""This represents a pop 3 account"""
|
||||
|
||||
def __init__(self, domain, localpart):
|
||||
"""Creates a new pop3 mail account"""
|
||||
if localpart in domain.pop3accounts.keys():
|
||||
raise POP3AccountExists
|
||||
MailAccount.__init__(self, domain, localpart)
|
||||
self.logger.debug("adding address %s@%s." % (self.localpart,
|
||||
self.domain.name))
|
||||
self.setPassword(tools.generatePassword())
|
||||
self.setSysUser(domain.getNextUser("pop3"))
|
||||
self.domain.addMailAlias(MailAlias(self.domain,
|
||||
self.localpart, self.sysuser))
|
||||
|
||||
def setPassword(self, newpassword):
|
||||
self.password = newpassword
|
||||
self.logger.debug("set password for %s to %s." %
|
||||
(str(self), self.password))
|
||||
|
||||
def setSysUser(self, username):
|
||||
self.sysuser = username
|
||||
self.logger.debug("set system user for %s to %s" %
|
||||
(str(self), self.sysuser))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
prefs = GNVPrefs()
|
||||
domain = GNVDomain("test.local", prefs)
|
||||
domain.addPOP3Account(POP3Account(domain, "test"))
|
||||
domain.addMailAlias(MailAlias(domain, "klaus", "klaus@test.de"))
|
|
@ -1,50 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
import unittest
|
||||
import psycopg
|
||||
|
||||
class TestDBConnection(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""
|
||||
set up database connection used in tests
|
||||
"""
|
||||
self.cnx = psycopg.connect("host=localhost user=gnuviech password=SIKKnsyXsV5yU dbname=gnuviechadmin")
|
||||
self.cr = self.cnx.cursor()
|
||||
|
||||
def testSelectMailAliases(self):
|
||||
"""
|
||||
select all mail aliases
|
||||
"""
|
||||
self.cr.execute('SELECT * FROM mailalias')
|
||||
self.cnx.commit()
|
||||
|
||||
print self.cr.description
|
||||
|
||||
result = self.cr.fetchall()
|
||||
for line in result:
|
||||
print line
|
||||
|
||||
def testSelectMailPasswd(self):
|
||||
"""
|
||||
select all mail passwords
|
||||
"""
|
||||
self.cr.execute('SELECT * FROM mailpasswd')
|
||||
self.cnx.commit()
|
||||
|
||||
print self.cr.description
|
||||
|
||||
result = cr.fetchall()
|
||||
for line in result:
|
||||
print line
|
||||
|
||||
def testSelectDomains(self):
|
||||
"""
|
||||
select all domains
|
||||
"""
|
||||
self.cr.execute('SELECT DISTINCT domain FROM mailalias')
|
||||
self.cnx.commit()
|
||||
|
||||
print self.cr.description
|
||||
|
||||
result = cr.fetchall()
|
||||
for line in result:
|
||||
print line
|
|
@ -1,8 +0,0 @@
|
|||
#
|
||||
# Business methoden
|
||||
#
|
||||
def login(login, password):
|
||||
if (('jan' == login) and ('jan' == password)):
|
||||
return 'XXX'
|
||||
else:
|
||||
return None
|
|
@ -1,39 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# (c) 2006 Jan Dittberner <jan@dittberner.info>
|
||||
# $Id$
|
||||
#
|
||||
|
||||
from ZSI.ServiceContainer import ServiceContainer
|
||||
from ZSI.dispatch import SOAPRequestHandler
|
||||
from gnuviechadmin_services_server import *
|
||||
|
||||
class mySOAPRequestHandler(SOAPRequestHandler):
|
||||
'''
|
||||
Own SOAP request handler implementation.
|
||||
'''
|
||||
def do_GET(self):
|
||||
'''
|
||||
Process the HTTP GET method, delivers service's WSDL.
|
||||
'''
|
||||
self.send_xml(service._wsdl)
|
||||
|
||||
def AsServer(iporhost='', port=80, services=(),
|
||||
RequestHandlerClass=SOAPRequestHandler):
|
||||
"""
|
||||
iporhost -- IP address or hostname to bind to
|
||||
port -- TCP port
|
||||
services -- list of service instances
|
||||
"""
|
||||
address = (iporhost, port)
|
||||
sc = ServiceContainer(address, RequestHandlerClass=RequestHandlerClass)
|
||||
for service in services:
|
||||
path = service.getPost()
|
||||
sc.setNode(service, path)
|
||||
sc.serve_forever()
|
||||
|
||||
service = gnuviechadmin()
|
||||
|
||||
if __name__ == '__main__':
|
||||
AsServer(iporhost='localhost', port=8080, services=[service],
|
||||
RequestHandlerClass=mySOAPRequestHandler)
|
|
@ -1,74 +0,0 @@
|
|||
from gnuviechadminCommon.gnuviechadmin_services import *
|
||||
from ZSI.ServiceContainer import ServiceSOAPBinding
|
||||
import BusinessMethods
|
||||
|
||||
class gnuviechadmin(ServiceSOAPBinding):
|
||||
soapAction = {
|
||||
'https://ssl.gnuviech.info/gnuviechadmin/Authenticate': 'soap_Authenticate',
|
||||
}
|
||||
_wsdl = """<?xml version=\"1.0\" ?>
|
||||
<!--
|
||||
Webservice description for gnuviechadmin
|
||||
(c) 2006 Jan Dittberner <jan@dittberner.info>
|
||||
Version: $Id$
|
||||
--><wsdl:definitions name=\"gnuviechadmin\" targetNamespace=\"https://ssl.gnuviech.info/gnuviechadmin/\" xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:tns=\"https://ssl.gnuviech.info/gnuviechadmin/\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
|
||||
<wsdl:types>
|
||||
<xsd:schema targetNamespace=\"https://ssl.gnuviech.info/gnuviechadmin/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
|
||||
<xsd:element name=\"AuthCode\" type=\"xsd:string\"/>
|
||||
<xsd:element name=\"LoginInfo\">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence maxOccurs=\"1\" minOccurs=\"1\">
|
||||
<xsd:element name=\"login\" type=\"xsd:string\"/>
|
||||
<xsd:element name=\"password\" type=\"xsd:string\"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
</wsdl:types>
|
||||
<wsdl:message name=\"AuthResponse\">
|
||||
<wsdl:part element=\"tns:AuthCode\" name=\"AuthResponse\"/>
|
||||
</wsdl:message>
|
||||
<wsdl:message name=\"AuthRequest\">
|
||||
<wsdl:part element=\"tns:LoginInfo\" name=\"AuthRequest\"/>
|
||||
</wsdl:message>
|
||||
<wsdl:portType name=\"gnuviechadmin\">
|
||||
<wsdl:operation name=\"Authenticate\">
|
||||
<wsdl:input message=\"tns:AuthRequest\"/>
|
||||
<wsdl:output message=\"tns:AuthResponse\"/>
|
||||
</wsdl:operation>
|
||||
</wsdl:portType>
|
||||
<wsdl:binding name=\"gnuviechadminSOAP\" type=\"tns:gnuviechadmin\">
|
||||
<soap:binding style=\"document\" transport=\"http://schemas.xmlsoap.org/soap/http\"/>
|
||||
<wsdl:operation name=\"Authenticate\">
|
||||
<soap:operation soapAction=\"https://ssl.gnuviech.info/gnuviechadmin/Authenticate\"/>
|
||||
<wsdl:input>
|
||||
<soap:body parts=\" AuthRequest\" use=\"literal\"/>
|
||||
</wsdl:input>
|
||||
<wsdl:output>
|
||||
<soap:body parts=\" AuthResponse\" use=\"literal\"/>
|
||||
</wsdl:output>
|
||||
</wsdl:operation>
|
||||
</wsdl:binding>
|
||||
<wsdl:service name=\"gnuviechadmin\">
|
||||
<wsdl:port binding=\"tns:gnuviechadminSOAP\" name=\"gnuviechadminSOAP\">
|
||||
<soap:address location=\"https://ssl.gnuviech.info/gnuviechadmin\"/>
|
||||
</wsdl:port>
|
||||
</wsdl:service>
|
||||
</wsdl:definitions>"""
|
||||
|
||||
def __init__(self, post='/gnuviechadmin', **kw):
|
||||
ServiceSOAPBinding.__init__(self, post)
|
||||
|
||||
|
||||
def soap_Authenticate(self, ps):
|
||||
# input vals in request object
|
||||
args = ps.Parse( AuthRequestWrapper )
|
||||
|
||||
# assign return values to response object
|
||||
class SimpleTypeWrapper(str): typecode = AuthResponseWrapper()
|
||||
|
||||
# WARNING specify value eg. SimpleTypeWrapper(1)
|
||||
response = SimpleTypeWrapper(BusinessMethods.login(login=args._login, password=args._password))
|
||||
|
||||
# Return the response
|
||||
return response
|
|
@ -1,43 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import gnuviech, sys
|
||||
import gnuviech.tools
|
||||
from gnuviech.gnvdomain import GNVDomain
|
||||
|
||||
class Test:
|
||||
def __init__(self, prefs):
|
||||
self.logger = prefs.getLogger(self)
|
||||
self.prefs = prefs
|
||||
|
||||
def doTest(self):
|
||||
self.logger.debug(str(prefs))
|
||||
minlen = 0
|
||||
avglen = 0
|
||||
maxlen = 0
|
||||
pwds = 20
|
||||
for i in range(pwds):
|
||||
pwd = gnuviech.tools.generatePassword()
|
||||
self.logger.debug("%02d: %s (%d)" % (i, pwd, len(pwd)))
|
||||
if (minlen == 0) or (len(pwd) < minlen): minlen = len(pwd)
|
||||
if (len(pwd) > maxlen): maxlen = len(pwd)
|
||||
avglen += len(pwd)
|
||||
avglen = avglen/pwds
|
||||
self.logger.debug("""average password length: %d
|
||||
minimum password length: %d
|
||||
maximum password length: %d""" % (avglen, minlen, maxlen))
|
||||
|
||||
for address in ('jan@dittberner.info', 'jan', 'jan@gnuelf#test.de',
|
||||
'd.arnstadt@gmx.net'):
|
||||
if gnuviech.tools.checkEmail(address):
|
||||
self.logger.debug("%s is a valid email address." % address)
|
||||
else:
|
||||
self.logger.debug("%s is an invalid email address." % address)
|
||||
|
||||
domain = GNVDomain("dittberner.info", self.prefs)
|
||||
self.logger.debug("Domain %s." % domain)
|
||||
domain = GNVDomain("jesusgemeindesohland.de", self.prefs)
|
||||
self.logger.debug("Domain %s." % domain)
|
||||
|
||||
if __name__ == "__main__":
|
||||
prefs = gnuviech.GNVPrefs()
|
||||
Test(prefs).doTest()
|
|
@ -1,30 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
"""
|
||||
XML-RPC server for gnuviech-admin tool
|
||||
(c) 2006 Jan Dittberner
|
||||
$Id$
|
||||
"""
|
||||
from DocXMLRPCServer import DocXMLRPCServer
|
||||
from GnuviechAdmin import ServiceFacade, Settings
|
||||
import logging, threading
|
||||
|
||||
logger = logging.getLogger()
|
||||
hdlr = logging.FileHandler('xmlrpcserver.log')
|
||||
f = logging.Formatter('%(asctime)s %(levelname)s %(module)s: %(message)s')
|
||||
hdlr.setFormatter(f)
|
||||
logger.addHandler(hdlr)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
server = DocXMLRPCServer(Settings.RPCSERVERADDRESS)
|
||||
server.register_introspection_functions()
|
||||
server.register_instance(ServiceFacade())
|
||||
|
||||
try:
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
server.server_close()
|
||||
|
||||
for thread in [t for t in threading.enumerate() if t.isAlive() \
|
||||
and isinstance(t, threading._Timer)]:
|
||||
logger.debug("Stopping timer thread %s" % thread.getName())
|
||||
thread.cancel()
|
|
@ -1,6 +0,0 @@
|
|||
<?php
|
||||
$config["db_host"] = "localhost";
|
||||
$config["db_name"] = "gnuviechadmin";
|
||||
$config["db_user"] = "gnuviech";
|
||||
$config["db_pass"] = "test";
|
||||
?>
|
105
createclient.py
Normal file
105
createclient.py
Normal file
|
@ -0,0 +1,105 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# This file is part of gnuviechadmin.
|
||||
#
|
||||
# Author: Jan Dittberner <jan@dittberner.info>
|
||||
# Copyright (c) 2007 Jan Dittberner
|
||||
# Version: $Id$
|
||||
|
||||
import getopt, sys
|
||||
from sqlalchemy import *
|
||||
|
||||
from gnuviechadmin import client
|
||||
|
||||
def usage():
|
||||
print """Usage: %s [-h|--help] [-v|--verbose]
|
||||
[-t <title>|--title=<title>]
|
||||
-f <firstname>|--firstname=<firstname> -l <lastname>|--lastname=<lastname>
|
||||
-a <address1>|--address=<address1> [--address2=<address2>]
|
||||
-z <zip>|--zip=<zip> -c <city>|--city=<city> [--country=<isocode>]
|
||||
[-o <organisation>|--organisation=<organisation>]
|
||||
-e <email>|--email=<email> -p <phone>|--phone=<phone>
|
||||
[-m <mobile>|--mobile=<mobile>] [-x <fax>|--fax=<fax>]
|
||||
|
||||
General options:
|
||||
-h, --help show this usage message and exit
|
||||
-v, --verbose verbose operation
|
||||
|
||||
Mandatory client data options:
|
||||
-f, --firstname firstname
|
||||
-l, --lastname lastname
|
||||
-a, --address street address
|
||||
-z, --zip zip or postal code
|
||||
-c, --city city or location
|
||||
-e, --email contact email address
|
||||
-p, --phone telephone number
|
||||
|
||||
Optional client data options:
|
||||
--address2 optional second line of the street address
|
||||
-o, --organisation option organisation
|
||||
--country country (defaults to de)
|
||||
-t, --title optional title
|
||||
-m, --mobile optional mobile number
|
||||
-x, --fax optional fax number
|
||||
""" % (sys.argv[0])
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.gnu_getopt(sys.argv[1:],
|
||||
"hvf:l:a:z:c:e:p:o:t:m:x:",
|
||||
["help", "verbose", "firstname=",
|
||||
"lastname=", "address=", "zip=",
|
||||
"city=", "email=", "phone=",
|
||||
"address2=", "organisation=",
|
||||
"country=", "title=", "mobile=",
|
||||
"fax="])
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
clientdata = {}
|
||||
verbose = False
|
||||
for o, a in opts:
|
||||
if o in ("-v", "--verbose"):
|
||||
verbose = True
|
||||
if o in ("-h", "--help"):
|
||||
usage()
|
||||
sys.exit()
|
||||
if o in ("-f", "--firstname"):
|
||||
clientdata["firstname"] = a
|
||||
if o in ("-l", "--lastname"):
|
||||
clientdata["lastname"] = a
|
||||
if o in ("-a", "--address"):
|
||||
clientdata["address1"] = a
|
||||
if o in ("-z", "--zip"):
|
||||
clientdata["zip"] = a
|
||||
if o in ("-c", "--city"):
|
||||
clientdata["city"] = a
|
||||
if o == "--country":
|
||||
clientdata["country"] = a
|
||||
if o in ("-t", "--title"):
|
||||
clientdata["title"] = a
|
||||
if o in ("-m", "--mobile"):
|
||||
clientdata["mobile"] = a
|
||||
if o in ("-e", "--email"):
|
||||
clientdata["email"] = a
|
||||
if o in ("-o", "--organisation"):
|
||||
clientdata["organisation"] = a
|
||||
if o in ("-x", "--fax"):
|
||||
clientdata["fax"] = a
|
||||
if o in ("-p", "--phone"):
|
||||
clientdata["phone"] = a
|
||||
if verbose:
|
||||
print "parsed client data is ", clientdata
|
||||
myclient = client.Client(clientdata)
|
||||
if not myclient:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
sess = create_session()
|
||||
sess.save(myclient)
|
||||
sess.flush()
|
||||
if verbose:
|
||||
print myclient
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
278
database.sql
278
database.sql
|
@ -1,278 +0,0 @@
|
|||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
SET search_path = public, pg_catalog;
|
||||
|
||||
--
|
||||
-- TOC entry 2 (OID 17132)
|
||||
-- Name: country; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE country (
|
||||
id serial NOT NULL,
|
||||
name character varying(40) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3 (OID 17137)
|
||||
-- Name: client; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE client (
|
||||
id serial NOT NULL,
|
||||
firstname character varying(40) NOT NULL,
|
||||
lastname character varying(40) NOT NULL,
|
||||
address1 character varying(40) NOT NULL,
|
||||
address2 character varying(40),
|
||||
country integer NOT NULL,
|
||||
town character varying(50) NOT NULL,
|
||||
zipcode character(5) NOT NULL,
|
||||
state character varying(40),
|
||||
active boolean DEFAULT false NOT NULL,
|
||||
phone character varying(20),
|
||||
mobile character varying(20),
|
||||
reseller_id integer
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 4 (OID 17143)
|
||||
-- Name: reseller; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE reseller (
|
||||
id serial NOT NULL,
|
||||
name character varying(40) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 5 (OID 17148)
|
||||
-- Name: email; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE email (
|
||||
id serial NOT NULL,
|
||||
email character varying(128) NOT NULL,
|
||||
client integer,
|
||||
verified boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 6 (OID 17154)
|
||||
-- Name: sysuser; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE sysuser (
|
||||
id serial NOT NULL,
|
||||
name character varying(12) NOT NULL,
|
||||
"type" integer DEFAULT 0 NOT NULL,
|
||||
home character varying(128),
|
||||
shell boolean,
|
||||
"password" character varying(64),
|
||||
client integer NOT NULL,
|
||||
toupdate boolean DEFAULT false NOT NULL,
|
||||
md5pass character varying(32),
|
||||
sysuid integer
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 7 (OID 17161)
|
||||
-- Name: domain; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE "domain" (
|
||||
id serial NOT NULL,
|
||||
domainname character varying(64) NOT NULL,
|
||||
client integer NOT NULL,
|
||||
status integer DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 8 (OID 17167)
|
||||
-- Name: zone; Type: TABLE; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE TABLE "zone" (
|
||||
id serial NOT NULL,
|
||||
"domain" integer NOT NULL,
|
||||
"type" character varying(5) NOT NULL,
|
||||
ttl integer NOT NULL,
|
||||
mxprio integer,
|
||||
resource character varying(256),
|
||||
toupdate boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 12 (OID 17171)
|
||||
-- Name: reseller_name_idx; Type: INDEX; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX reseller_name_idx ON reseller USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 9 (OID 17172)
|
||||
-- Name: country_name_idx; Type: INDEX; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX country_name_idx ON country USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 19 (OID 17173)
|
||||
-- Name: sysuser_type_idx; Type: INDEX; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE INDEX sysuser_type_idx ON sysuser USING btree ("type");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 18 (OID 17231)
|
||||
-- Name: sysuser_sysuid_idx; Type: INDEX; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX sysuser_sysuid_idx ON sysuser USING btree (sysuid);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 10 (OID 17174)
|
||||
-- Name: country_pkey; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY country
|
||||
ADD CONSTRAINT country_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 11 (OID 17176)
|
||||
-- Name: client_pkey; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY client
|
||||
ADD CONSTRAINT client_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 22 (OID 17178)
|
||||
-- Name: $1; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY client
|
||||
ADD CONSTRAINT "$1" FOREIGN KEY (country) REFERENCES country(id) ON UPDATE NO ACTION ON DELETE NO ACTION;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 13 (OID 17182)
|
||||
-- Name: reseller_pkey; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY reseller
|
||||
ADD CONSTRAINT reseller_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 23 (OID 17184)
|
||||
-- Name: $2; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY client
|
||||
ADD CONSTRAINT "$2" FOREIGN KEY (reseller_id) REFERENCES reseller(id) ON UPDATE NO ACTION ON DELETE NO ACTION;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 15 (OID 17188)
|
||||
-- Name: email_pkey; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY email
|
||||
ADD CONSTRAINT email_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 14 (OID 17190)
|
||||
-- Name: email_email_key; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY email
|
||||
ADD CONSTRAINT email_email_key UNIQUE (email);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 24 (OID 17192)
|
||||
-- Name: $1; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY email
|
||||
ADD CONSTRAINT "$1" FOREIGN KEY (client) REFERENCES client(id) ON UPDATE NO ACTION ON DELETE NO ACTION;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 17 (OID 17196)
|
||||
-- Name: sysuser_pkey; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY sysuser
|
||||
ADD CONSTRAINT sysuser_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 16 (OID 17198)
|
||||
-- Name: sysuser_name_key; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY sysuser
|
||||
ADD CONSTRAINT sysuser_name_key UNIQUE (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 25 (OID 17200)
|
||||
-- Name: $1; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY sysuser
|
||||
ADD CONSTRAINT "$1" FOREIGN KEY (client) REFERENCES client(id) ON UPDATE NO ACTION ON DELETE NO ACTION;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 20 (OID 17204)
|
||||
-- Name: domain_pkey; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY "domain"
|
||||
ADD CONSTRAINT domain_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 26 (OID 17206)
|
||||
-- Name: $1; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY "domain"
|
||||
ADD CONSTRAINT "$1" FOREIGN KEY (client) REFERENCES client(id) ON UPDATE NO ACTION ON DELETE NO ACTION;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 21 (OID 17210)
|
||||
-- Name: zone_pkey; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY "zone"
|
||||
ADD CONSTRAINT zone_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 27 (OID 17212)
|
||||
-- Name: $1; Type: CONSTRAINT; Schema: public; Owner: gnuviech
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY "zone"
|
||||
ADD CONSTRAINT "$1" FOREIGN KEY ("domain") REFERENCES "domain"(id) ON UPDATE NO ACTION ON DELETE NO ACTION;
|
||||
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# XML-RPC-Client
|
||||
# (c) 2006 Jan Dittberner
|
||||
# version: $Id$
|
||||
#
|
||||
from xmlrpclib import ServerProxy
|
||||
import logging, sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
server = ServerProxy('http://localhost:8080')
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
sessionid = None
|
||||
try:
|
||||
sessionid = server.login('jan', 'heyyou97')
|
||||
if sessionid:
|
||||
print "Session %s" % sessionid
|
||||
print server.listdomains(sessionid)
|
||||
server.logout(sessionid)
|
||||
else:
|
||||
print "login failed"
|
||||
except Exception, v:
|
||||
logger.exception(v)
|
||||
if sessionid is not None:
|
||||
try:
|
||||
server.logout(sessionid)
|
||||
except Exception, vn:
|
||||
logger.exception(vn)
|
|
@ -1,42 +0,0 @@
|
|||
from mod_python import apache, Session
|
||||
from genshi.template import TemplateLoader, TemplateNotFound
|
||||
from genshi import ParseError
|
||||
|
||||
def findtemplate(uri):
|
||||
templates = {"/" : "index.xml"}
|
||||
if uri in templates:
|
||||
return templates[uri]
|
||||
return None
|
||||
|
||||
def handler(req):
|
||||
session = Session.Session(req)
|
||||
try:
|
||||
session['hits'] += 1
|
||||
except:
|
||||
session['hits'] = 1
|
||||
|
||||
session.save()
|
||||
|
||||
template = findtemplate(req.uri)
|
||||
if template:
|
||||
|
||||
loader = TemplateLoader([req.document_root()])
|
||||
try:
|
||||
req.content_type = "text/html; charset=UTF-8"
|
||||
tmpl = loader.load(template)
|
||||
stream = tmpl.generate(title='Hello World: Reloaded',
|
||||
hits=session['hits'])
|
||||
pagebuffer = stream.render('xhtml')
|
||||
except TemplateNotFound, tnf:
|
||||
req.content_type = "text/plain; charset=UTF-8"
|
||||
pagebuffer = str(tnf)
|
||||
except ParseError, pe:
|
||||
req.content_type = "text/plain; charset=UTF-8"
|
||||
pagebuffer = str(pe)
|
||||
|
||||
#pagebuffer = "Hits: %d\n" % session['hits']
|
||||
#pagebuffer += "Yippieh: I found %s -> %s!" % (req.uri, template)
|
||||
|
||||
req.write(pagebuffer)
|
||||
return (apache.OK)
|
||||
return (apache.HTTP_NOT_FOUND)
|
|
@ -1,9 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>$title</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>$title</h1>
|
||||
<p>Hits: $hits</p>
|
||||
</body>
|
||||
</html>
|
|
@ -1,88 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
from soapclient import soapclient
|
||||
|
||||
class GnuviechAdminGnome:
|
||||
"""GnuviechAdmin Gnome Interface"""
|
||||
_version = '0.1'
|
||||
|
||||
def delete_event(self, widget, event, data = None):
|
||||
return False
|
||||
|
||||
def duplicate_text(self, widget, data = None):
|
||||
text = self.textfield.get_text()
|
||||
self.label.set_text(self.soapclient.echo(text))
|
||||
|
||||
def destroy_event(self, widget, data = None):
|
||||
gtk.main_quit()
|
||||
|
||||
def show_aboutbox(self, widget, data = None):
|
||||
aboutbox = gtk.AboutDialog()
|
||||
aboutbox.set_authors(['Jan Dittberner <jan@dittberner.info>'])
|
||||
aboutbox.set_name("GnuviechAdmin\nGNOME frontend")
|
||||
aboutbox.set_copyright('(c) 2006 Jan Dittberner')
|
||||
aboutbox.set_license('This program is licensed under the terms of the GNU General Public License (GPL) version 2 or later.')
|
||||
aboutbox.set_version(self._version)
|
||||
aboutbox.show()
|
||||
|
||||
def _create_menubar(self):
|
||||
menubar = gtk.MenuBar()
|
||||
menu = gtk.Menu()
|
||||
menuitem = gtk.MenuItem(label = '_Exit')
|
||||
menuitem.connect_object("activate", gtk.Widget.destroy, self.window)
|
||||
|
||||
menu.append(menuitem)
|
||||
|
||||
rootmenu = gtk.MenuItem('_File')
|
||||
rootmenu.set_submenu(menu)
|
||||
|
||||
menubar.append(rootmenu)
|
||||
|
||||
menu = gtk.Menu()
|
||||
menuitem = gtk.MenuItem(label = '_About')
|
||||
menuitem.connect("activate", self.show_aboutbox)
|
||||
|
||||
menu.append(menuitem)
|
||||
|
||||
rootmenu = gtk.MenuItem('_Help')
|
||||
rootmenu.set_right_justified(True)
|
||||
rootmenu.set_submenu(menu)
|
||||
|
||||
menubar.append(rootmenu)
|
||||
return menubar
|
||||
|
||||
def __init__( self ):
|
||||
self.soapclient = soapclient.SOAPClient()
|
||||
|
||||
self.window = gtk.Window()
|
||||
self.window.connect("delete_event", self.delete_event)
|
||||
self.window.connect("destroy", self.destroy_event)
|
||||
|
||||
button = gtk.Button("Hello world")
|
||||
#button.connect_object("clicked", gtk.Widget.destroy, self.window)
|
||||
|
||||
self.textfield = gtk.Entry()
|
||||
button.connect("clicked", self.duplicate_text)
|
||||
|
||||
self.label = gtk.Label()
|
||||
menubar = self._create_menubar()
|
||||
|
||||
vbox = gtk.VBox()
|
||||
vbox.add(menubar)
|
||||
vbox.add(button)
|
||||
vbox.add(self.textfield)
|
||||
vbox.add(self.label)
|
||||
|
||||
self.window.add(vbox)
|
||||
|
||||
self.window.show_all()
|
||||
|
||||
def main(self):
|
||||
gtk.main()
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = GnuviechAdminGnome()
|
||||
g.main()
|
|
@ -1,4 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
"""
|
||||
This package contains the SOAP client for the gnuviech admin tool
|
||||
"""
|
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
import sys
|
||||
import socket
|
||||
from ZSI import ServiceProxy
|
||||
|
||||
class SOAPClient:
|
||||
def __init__(self):
|
||||
url = 'http://localhost:8080/gnuviechadmin'
|
||||
self.service = ServiceProxy(url, use_wsdl=True,
|
||||
tracefile=sys.stdout)
|
||||
print 'service is ', self.service
|
||||
print self.service.__dict__
|
||||
|
||||
def authenticate(self, login, password):
|
||||
try:
|
||||
response = self.service.Authenticate(login=login, password=password)
|
||||
print response
|
||||
except socket.error:
|
||||
return "couldn't connect"
|
||||
|
||||
if __name__ == "__main__":
|
||||
client = SOAPClient()
|
||||
print client.authenticate("jan", "jan")
|
11
gnuviechadmin/__init__.py
Normal file
11
gnuviechadmin/__init__.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
# This file is part of gnuviechadmin.
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Author: Jan Dittberner <jan@dittberner.info>
|
||||
# Copyright (c) 2007, Jan Dittberner
|
||||
# Version: $Id$
|
||||
|
||||
"""
|
||||
This is the gnuviechadmin package.
|
||||
|
||||
"""
|
78
gnuviechadmin/client.py
Normal file
78
gnuviechadmin/client.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
# This file is part of gnuviechadmin.
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Author: Jan Dittberner <jan@dittberner.info>
|
||||
# Copyright (c) 2007 Jan Dittberner
|
||||
# Version: $Id$
|
||||
|
||||
from sqlalchemy import *
|
||||
|
||||
meta = BoundMetaData('sqlite:///database.txt')
|
||||
client_table = Table('clients', meta,
|
||||
Column('clientid', Integer, primary_key=True),
|
||||
Column('title', String(10)),
|
||||
Column('firstname', String(64), nullable=False),
|
||||
Column('lastname', String(64), nullable=False),
|
||||
Column('address1', String(64), nullable=False),
|
||||
Column('address2', String(64)),
|
||||
Column('zip', String(7), nullable=False),
|
||||
Column('city', String(64), nullable=False),
|
||||
Column('country', String(5), nullable=False),
|
||||
Column('phone', String(20), nullable=False),
|
||||
Column('mobile', String(20)),
|
||||
Column('fax', String(20)),
|
||||
Column('email', String(64), unique=True, nullable=False))
|
||||
client_table.create(checkfirst=True)
|
||||
|
||||
class Client(object):
|
||||
"""This class provides a client representation"""
|
||||
def __init__(self, clientdata):
|
||||
mandatory = ('firstname', 'lastname', 'address1', 'zip', 'city',
|
||||
'email', 'phone', 'country')
|
||||
data = {"country": "de", "title": None, "address2": None,
|
||||
"mobile": None, "fax": None, "organisation": None}
|
||||
for key in clientdata.keys():
|
||||
data[key] = clientdata[key]
|
||||
for key in mandatory:
|
||||
if not key in data:
|
||||
print "mandatory client field %s is missing" % (key)
|
||||
self = None
|
||||
return
|
||||
self.title = data["title"]
|
||||
self.firstname = data["firstname"]
|
||||
self.lastname = data["lastname"]
|
||||
self.address1 = data["address1"]
|
||||
self.address2 = data["address2"]
|
||||
self.organisation = data["organisation"]
|
||||
self.zip = data["zip"]
|
||||
self.city = data["city"]
|
||||
self.country = data["country"]
|
||||
self.phone = data["phone"]
|
||||
self.mobile = data["mobile"]
|
||||
self.fax = data["fax"]
|
||||
self.email = data["email"]
|
||||
|
||||
def __repr__(self):
|
||||
return """Client (Id %(clientid)d):
|
||||
Name: %(title)s %(firstname)s %(lastname)s
|
||||
Address: %(address1)s
|
||||
%(address2)s
|
||||
%(zip)s %(city)s (%(country)s)
|
||||
Phone: %(phone)s
|
||||
Mobile: %(mobile)s
|
||||
Fax: %(fax)s
|
||||
Email: %(email)s""" % ({'clientid' : self.clientid,
|
||||
'title' : self.title,
|
||||
'firstname' : self.firstname,
|
||||
'lastname' : self.lastname,
|
||||
'address1' : self.address1,
|
||||
'address2' : self.address2,
|
||||
'zip' : self.zip,
|
||||
'city' : self.city,
|
||||
'country' : self.country,
|
||||
'phone' : self.phone,
|
||||
'mobile' : self.mobile,
|
||||
'fax' : self.fax,
|
||||
'email' : self.email})
|
||||
|
||||
clientmapper = mapper(Client, client_table)
|
|
@ -1,2 +0,0 @@
|
|||
# configuration for PEAR
|
||||
php_value include_path "/home/jan/pear/php/"
|
|
@ -1,4 +0,0 @@
|
|||
all:
|
||||
|
||||
clean:
|
||||
-rm -f *~
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* SOAP client class for accessing the gnuviech adminstration tool SOAP
|
||||
* service.
|
||||
* @author Jan Dittberner <jan@dittberner.info>
|
||||
* @version $Id$
|
||||
*/
|
||||
require_once('SOAP/Client.php');
|
||||
|
||||
/**
|
||||
* SOAP requester.
|
||||
*/
|
||||
class SOAPRequester {
|
||||
/**
|
||||
* SOAP_Client-Instanz.
|
||||
* @access private
|
||||
*/
|
||||
var $soapclient;
|
||||
|
||||
/**
|
||||
* Constructor expecting a settings array.
|
||||
* @param settings with options protocol, hostname, portnumber, path
|
||||
* @access public
|
||||
*/
|
||||
function SOAPRequester($settings) {
|
||||
$this->soapclient = new SOAP_Client(sprintf("%s://%s:%d/%s",
|
||||
$settings['protocol'],
|
||||
$settings['hostname'],
|
||||
$settings['portnumber'],
|
||||
$settings['path']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the echo method at the remote SOAP server.
|
||||
* @param String parameter
|
||||
* @return twice the String if the remote call is successful
|
||||
*/
|
||||
function callecho($param) {
|
||||
$options = array('trace' => 1);
|
||||
|
||||
$ret = $this->soapclient->call('echo',
|
||||
$params = array('param0' => $param),
|
||||
$options);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Unittest for the SOAPRequester.
|
||||
* @author Jan Dittberner <jan@dittberner.info>
|
||||
* @version $Id$
|
||||
*/
|
||||
require_once('PHPUnit.php');
|
||||
require_once('SOAPRequester.php');
|
||||
|
||||
/**
|
||||
* TestCase for SOAPRequester.
|
||||
*/
|
||||
class TestSOAPRequester extends PHPUnit_TestCase {
|
||||
/**
|
||||
* SOAPRequester-Instanz.
|
||||
*/
|
||||
var $requester;
|
||||
|
||||
/**
|
||||
* Sets up the test case.
|
||||
* @see PHPUnit_TestCase#setUp()
|
||||
*/
|
||||
function setUp() {
|
||||
$settings = array('protocol' => 'http',
|
||||
'hostname' => 'localhost',
|
||||
'portnumber' => 8080,
|
||||
'path' => '');
|
||||
$this->requester = new SOAPRequester($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the SOAPRequester class's callEcho method.
|
||||
* @see SOAPRequester#callEcho(string)
|
||||
*/
|
||||
function testCallEcho() {
|
||||
$result = $this->requester->callEcho('Test');
|
||||
$this->assertEquals('TestTest', $result);
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,9 +0,0 @@
|
|||
<div>
|
||||
<hr/>
|
||||
<a href="start.php"><?php print (_("To start page")); ?></a>
|
||||
</div>
|
||||
<div class="copyright">
|
||||
© 2003 Jan Dittberner
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,7 +0,0 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>GNU-Viech Administration tool</title>
|
||||
<link rel="stylesheet" href="format.css" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
require("wantauth.php");
|
||||
require("tools.php");
|
||||
$dbh=db_open();
|
||||
session_start();
|
||||
include("userhead.php");
|
||||
include("domainstatustypes.php");
|
||||
?>
|
||||
<div>
|
||||
<?php
|
||||
$query=sprintf("SELECT * FROM domain WHERE client=%d",
|
||||
$_SESSION["client"]);
|
||||
$result=db_query($dbh, $query);
|
||||
|
||||
$rows=db_num_rows($result);
|
||||
if ($rows==0) {
|
||||
print("<p>" . _("You don't have any domains registered.") . "</p>");
|
||||
}
|
||||
else {
|
||||
print("<p>" . _("Here is a list of your currently registered domains.") . "</p>");
|
||||
printf("<table><tr><th>%s</th><th>%s</th></tr>",
|
||||
_("Domain name"), _("Status"));
|
||||
while ($row=db_fetch_array($result)) {
|
||||
printf("<tr><td>%s</td><td>%s</td></tr>",
|
||||
$row["domainname"], get_domainstatustype_name($row["status"]));
|
||||
}
|
||||
print("</table>");
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<a href="registerdomain.php"><?php print(_("Add domain")); ?></a>
|
||||
<?php
|
||||
include("commonfoot.php");
|
||||
?>
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
define("cDOMPENDING", 1);
|
||||
define("cDOMREG", 2);
|
||||
define("cDOMCON", 4);
|
||||
define("cDOMKK", 8);
|
||||
|
||||
function get_domainstatustype_name($typenum) {
|
||||
switch ($typenum) {
|
||||
case cDOMPENDING:
|
||||
return _("pending");
|
||||
break;
|
||||
case cDOMREG:
|
||||
return _("registered");
|
||||
break;
|
||||
case cDOMCON:
|
||||
return _("connected");
|
||||
break;
|
||||
case cDOMKK:
|
||||
return _("in transfer");
|
||||
break;
|
||||
default:
|
||||
return _("Unknown domain status");
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,8 +0,0 @@
|
|||
table.userhead {
|
||||
background:#FF8080;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-size:8px;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB |
|
@ -1,10 +0,0 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>GNU-Viech Administration tool</title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="start.php"><?php echo _("Login to the administration pages"); ?></a><br/>
|
||||
<a href="register.php"><?php echo _("Register as new client"); ?></a><br/>
|
||||
</body>
|
||||
</html>
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
require_once("tools.php");
|
||||
require_once("usertypes.php");
|
||||
$dbh = db_open();
|
||||
|
||||
function add_domain() {
|
||||
global $dbh;
|
||||
$query = sprintf("INSERT INTO domain (domainname, client) VALUES ('%s', %d)",
|
||||
$_POST["domainname"],
|
||||
$_SESSION["client"]);
|
||||
db_exec($dbh, $query);
|
||||
}
|
||||
|
||||
require("wantauth.php");
|
||||
session_start();
|
||||
|
||||
include("userhead.php");
|
||||
if (!isset($_POST["mode"])) {
|
||||
$mode = "step1";
|
||||
} else {
|
||||
$mode = $_POST["mode"];
|
||||
}
|
||||
|
||||
switch ($mode) {
|
||||
case "step1" :
|
||||
?>
|
||||
<p><?php print(_("Add new domain")); ?></p>
|
||||
<form action="<?php echo $PHP_SELF; ?>" method="post">
|
||||
<input type="hidden" name="mode" value="commit">
|
||||
<table>
|
||||
<tr><td><?php print(_("Domain name:")); ?></td><td><input type="text" name="domainname"></td></tr>
|
||||
<tr><td colspan="2" align="right"><input type="submit" name="submit" value="<?php print(_("add")); ?>"</td></tr>
|
||||
</table>
|
||||
</form>
|
||||
<?php
|
||||
break;
|
||||
case "commit" :
|
||||
add_domain();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
include("commonfoot.php");
|
||||
?>
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Test runner.
|
||||
* @author Jan Dittberner <jan@dittberner.info>
|
||||
* @version $Id$
|
||||
*/
|
||||
require_once('TestSOAPRequester.php');
|
||||
require_once('PHPUnit.php');
|
||||
|
||||
$suite = new PHPUnit_TestSuite('TestSOAPRequester');
|
||||
$result = PHPUnit::run($suite);
|
||||
|
||||
printf($result->toHTML());
|
||||
?>
|
185
php/setup.php
185
php/setup.php
|
@ -1,185 +0,0 @@
|
|||
<?php
|
||||
require("tools.php");
|
||||
require("usertypes.php");
|
||||
$dbh=db_open();
|
||||
|
||||
if (isset($_POST["mode"]) and $_POST["mode"]=="finish") {
|
||||
if (isset($_POST["adminpass1"]) and isset($_POST["adminpass2"])
|
||||
and $_POST["adminpass1"]!=$_POST["adminpass2"]) {
|
||||
header("Location: setup.php");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function create_country_list() {
|
||||
global $dbh;
|
||||
$countries = split("\n", $_POST["countries"]);
|
||||
foreach ($countries as $country) {
|
||||
$query = "INSERT INTO country (name) VALUES ('{$country}')";
|
||||
db_exec($dbh, $query);
|
||||
}
|
||||
}
|
||||
|
||||
function has_countries() {
|
||||
global $dbh;
|
||||
$result=db_query($dbh, "SELECT id FROM country");
|
||||
return (db_num_rows($result)!=0);
|
||||
}
|
||||
|
||||
function country_selbox($varname, $default=0) {
|
||||
global $dbh;
|
||||
$result=db_query($dbh, "SELECT * FROM country ORDER BY name");
|
||||
printf("<SELECT name=\"%s\">", $varname);
|
||||
while ($row=db_fetch_array($result)) {
|
||||
printf("<OPTION value=\"%d\"%s>%s</OPTION>",
|
||||
$row["id"], ($row["id"]==$default) ? " selected" : "",
|
||||
$row["name"]);
|
||||
}
|
||||
print("</SELECT>");
|
||||
}
|
||||
|
||||
function client_selbox($varname, $default=0) {
|
||||
global $dbh;
|
||||
$result=db_query($dbh, "SELECT cl.id, cl.firstname, cl.lastname, ".
|
||||
"cl.town, co.name FROM client cl, country co ".
|
||||
"WHERE cl.country=co.id ORDER BY cl.firstname, ".
|
||||
"cl.lastname");
|
||||
printf("<SELECT name=\"%s\">", $varname);
|
||||
while ($row=db_fetch_array($result)) {
|
||||
printf("<OPTION value=\"%d\"%s>%s %s (%s, %s)</OPTION>",
|
||||
$row["id"], ($row["id"]==$default) ? " selected" : "",
|
||||
$row["firstname"], $row["lastname"], $row["town"],
|
||||
$row["name"]);
|
||||
}
|
||||
print("</SELECT>");
|
||||
}
|
||||
|
||||
function enter_personal_data() {
|
||||
global $dbh;
|
||||
$query = sprintf("INSERT INTO client (firstname, lastname, ".
|
||||
"address1, country, town, zipcode, state, ".
|
||||
"active) VALUES ('%s', '%s', '%s', %d, '%s', ".
|
||||
"'%05d', '%s', true)",
|
||||
$_POST["firstname"],
|
||||
$_POST["lastname"],
|
||||
$_POST["address"],
|
||||
$_POST["country"],
|
||||
$_POST["town"],
|
||||
$_POST["zipcode"],
|
||||
$_POST["state"]);
|
||||
db_exec($dbh, $query);
|
||||
}
|
||||
|
||||
function has_personal_data() {
|
||||
global $dbh;
|
||||
$result=db_query($dbh, "SELECT id FROM client");
|
||||
return (db_num_rows($result)!=0);
|
||||
}
|
||||
|
||||
function setup_admin_account() {
|
||||
global $dbh;
|
||||
$query = sprintf("INSERT INTO sysuser (name, type, home, shell, ".
|
||||
"password, client, toupdate, md5pass, sysuid) ".
|
||||
"VALUES ('%s', %d, '/root', true, '%s', ".
|
||||
"%d, false, '%s', 0)",
|
||||
$_POST["adminuser"],
|
||||
cUSRADMIN,
|
||||
$_POST["adminpass1"],
|
||||
$_POST["clientid"],
|
||||
md5($_POST["adminpass1"]));
|
||||
db_exec($dbh, $query);
|
||||
}
|
||||
|
||||
function has_admin_account() {
|
||||
global $dbh;
|
||||
$query=sprintf("SELECT id FROM sysuser WHERE type=%d",
|
||||
cUSRADMIN);
|
||||
$result=db_query($dbh, $query);
|
||||
return (db_num_rows($result)!=0);
|
||||
}
|
||||
|
||||
include("commonhead.php");
|
||||
if (!isset($_POST["mode"])) {
|
||||
$mode = "step1";
|
||||
} else {
|
||||
$mode = $_POST["mode"];
|
||||
}
|
||||
|
||||
switch ($mode) :
|
||||
case "step1":
|
||||
?>
|
||||
<form action="<?php echo $PHP_SELF; ?>" method="post">
|
||||
<input type="hidden" name="mode" value="step2">
|
||||
<? if (!has_countries()) : ?>
|
||||
<table>
|
||||
<tr><td><?php echo _("Initial country list (each line one country)"); ?></td><td><textarea name="countries"></textarea></td></tr>
|
||||
<tr><td colspan="2" align="right"><input type="submit" name="submit" value="<?php echo _("generate country list"); ?>"></td></tr>
|
||||
</table>
|
||||
<?php
|
||||
else:
|
||||
echo _("You already have countries in your database");
|
||||
?>
|
||||
<br/><input type="submit" name="submit" value="<?php echo _("Skip to step 2"); ?>">
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</form>
|
||||
<?php
|
||||
break;
|
||||
case "step2":
|
||||
if (!has_countries()) create_country_list();
|
||||
?>
|
||||
<form action="<?php echo $PHP_SELF; ?>" method="post">
|
||||
<input type="hidden" name="mode" value="step3">
|
||||
<? if (!has_personal_data()) :?>
|
||||
<table>
|
||||
<tr><td><?php echo _("First name"); ?></td><td><input type="text" name="firstname"></td></tr>
|
||||
<tr><td><?php echo _("Last name"); ?></td><td><input type="text" name="lastname"></td></tr>
|
||||
<tr><td><?php echo _("Address"); ?></td><td><input type="text" name="address"></td></tr>
|
||||
<tr><td><?php echo _("ZIP Code"); ?></td><td><input type="text" name="zipcode"></td></tr>
|
||||
<tr><td><?php echo _("City/Town/Village"); ?></td><td><input type="text" name="town"></td></tr>
|
||||
<tr><td><?php echo _("State"); ?></td><td><input type="text" name="state"></td></tr>
|
||||
<tr><td><?php echo _("Country"); ?></td><td><?php country_selbox("country"); ?></td></tr>
|
||||
<tr><td colspan="2" align="right"><input type="submit" name="submit" value="<?php echo _("Submit personal data"); ?>"></td></tr>
|
||||
</table>
|
||||
<? else:
|
||||
echo _("You already have personal data in your database");
|
||||
?>
|
||||
<br/><input type="submit" name="submit" value="<?php echo _("Skip to step 3"); ?>">
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</form>
|
||||
<?php
|
||||
break;
|
||||
case "step3":
|
||||
if (!has_personal_data()) enter_personal_data();
|
||||
?>
|
||||
<form action="<? echo $PHP_SELF; ?>" method="post">
|
||||
<input type="hidden" name="mode" value="finish">
|
||||
<?php if (!has_admin_account()): ?>
|
||||
<table>
|
||||
<tr><td><?php echo _("Administrator client account"); ?></td><td><?php client_selbox("clientid"); ?></td></tr>
|
||||
<tr><td><?php echo _("Administrator username"); ?></td><td><input type="text" name="adminuser"></td></tr>
|
||||
<tr><td><?php echo _("Administrator password"); ?></td><td><input type="password" name="adminpass1"></td></tr>
|
||||
<tr><td><?php echo _("Administrator password (repeat)"); ?></td><td><input type="password" name="adminpass2"></td></tr>
|
||||
<tr><td colspan="2" align="right"><input type="submit" name="submit" value="<?php echo _("Submit administrator data"); ?>"></td></tr>
|
||||
</table>
|
||||
<?php else:
|
||||
echo _("You already have an admin user in your database");
|
||||
?>
|
||||
<br/><input type="submit" name="submit" value="<?php echo _("finish"); ?>">
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
<?php
|
||||
break;
|
||||
case "finish":
|
||||
if (!has_admin_account()) setup_admin_account();
|
||||
print(_("Congratulations, you are done with the initial setup!"));
|
||||
printf(_("You may now log in at the \"<a href=\"%s\">Start page</a>\"."), "start.php");
|
||||
break;
|
||||
default: ?>
|
||||
You are trying to trick me. I don't like this
|
||||
<?php endswitch; ?>
|
||||
</body>
|
||||
</html>
|
|
@ -1,45 +0,0 @@
|
|||
<?php
|
||||
require("wantauth.php");
|
||||
require("tools.php");
|
||||
|
||||
$dbh = db_open();
|
||||
|
||||
$username = strtolower(substr(trim($_SERVER['PHP_AUTH_USER']), 0, 12));
|
||||
$password = md5(substr(trim($_SERVER['PHP_AUTH_PW']), 0, 30));
|
||||
$query = "SELECT * FROM sysuser WHERE name='$username' AND md5pass='$password'";
|
||||
//echo $query;
|
||||
$result = db_query($dbh, $query) or die("query failed");
|
||||
|
||||
if (db_num_rows($result) == 0) {
|
||||
$logged_in = false;
|
||||
authenticate();
|
||||
echo $_SERVER['PHP_AUTH_USER'];
|
||||
echo "NOT LOGGED IN<br/>";
|
||||
} else {
|
||||
$logged_in = true;
|
||||
session_start();
|
||||
$row=db_fetch_array($result);
|
||||
$_SESSION["userid"]=$row["id"];
|
||||
}
|
||||
|
||||
include("commonhead.php");
|
||||
?>
|
||||
<div>
|
||||
<?php
|
||||
if (! $logged_in) {
|
||||
print("<p>" . _("You're not known to the system.") . "<br/>");
|
||||
print(_("Please go back and try again.") . "</p>");
|
||||
} else {
|
||||
include("userhead.php");
|
||||
// echo _("Session with ID: ").session_id()."<br/>";
|
||||
// echo _("UID: ").$_SESSION["userid"]."<br/>";
|
||||
print("<p>");
|
||||
printf(_("You may now see your <a href=\"%s\">Domain list</a>."),
|
||||
"domainlist.php");
|
||||
print("</p>");
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
include("commonfoot.php");
|
||||
?>
|
|
@ -1,37 +0,0 @@
|
|||
<?php
|
||||
|
||||
require("/var/local/gvadm/config.php");
|
||||
|
||||
function db_open() {
|
||||
global $config;
|
||||
$dbh = pg_connect("dbname=".$config["db_name"].
|
||||
" host=".$config["db_host"].
|
||||
" user=".$config["db_user"].
|
||||
" password=".$config["db_pass"])
|
||||
or die("Couldn't connect to database!");
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
function db_exec($dbh, $query) {
|
||||
pg_exec($dbh, $query)
|
||||
or die("Couldn't execute query!");
|
||||
}
|
||||
|
||||
function db_close($dbh) {
|
||||
pg_close($dbh)
|
||||
or die("Couldn't close database connection!");
|
||||
}
|
||||
|
||||
function db_query($dbh, $query) {
|
||||
$result = pg_exec($dbh, $query)
|
||||
or die("Couldn't query database!");
|
||||
return $result;
|
||||
}
|
||||
|
||||
function db_num_rows($result) {
|
||||
return pg_numrows($result);
|
||||
}
|
||||
|
||||
function db_fetch_array($sth) {
|
||||
return pg_fetch_array($sth);
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
include("commonhead.php");
|
||||
?>
|
||||
<div>
|
||||
<table class="userhead">
|
||||
<tr><td>
|
||||
<img src="images/gnu.png" width="45" height="43" alt="small GNU head"/>
|
||||
</td><td>
|
||||
<p>
|
||||
<?php
|
||||
require_once("usertypes.php");
|
||||
|
||||
$query=sprintf("SELECT name, type, client FROM sysuser WHERE id=%d",
|
||||
$_SESSION["userid"]);
|
||||
$result=db_query($dbh, $query);
|
||||
$row=db_fetch_array($result);
|
||||
printf(_("Logged in as %s (%s)"), $row["name"],
|
||||
get_usertype_name($row["type"]));
|
||||
|
||||
print("<br/>");
|
||||
$_SESSION["client"]=$row["client"];
|
||||
|
||||
$query=sprintf("SELECT client.*, country.name AS cname FROM client, country WHERE client.id=%d AND country.id=client.country", $row["client"]);
|
||||
$result=db_query($dbh, $query);
|
||||
$row=db_fetch_array($result);
|
||||
printf("%s %s, %s %s, %s %s, %s %s", $row["firstname"], $row["lastname"],
|
||||
$row["address1"], $row["address2"], $row["zipcode"], $row["town"],
|
||||
$row["state"], $row["cname"]);
|
||||
?>
|
||||
</p></td></tr></table>
|
||||
</div>
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
define("cUSRADMIN",255);
|
||||
define("cUSRWEB",128);
|
||||
define("cUSRMAIL",64);
|
||||
define("cUSRNONE",0);
|
||||
|
||||
function get_usertype_name($usertype) {
|
||||
switch ($usertype) {
|
||||
case cUSRADMIN:
|
||||
return _("Administrator");
|
||||
break;
|
||||
case cUSRWEB:
|
||||
return _("Web user");
|
||||
break;
|
||||
case cUSRMAIL:
|
||||
return _("Mail user");
|
||||
break;
|
||||
case cUSRNONE:
|
||||
default:
|
||||
return _("Unknown user type");
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* start a request for HTTP Authentication
|
||||
*/
|
||||
function authenticate() {
|
||||
header('WWW-Authenticate: Basic realm="GNU-viech administration tool"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo _("You are not allowed to use this application without valid authentication data.");
|
||||
printf(_("You entered: %s, %s (md5: %s)"),
|
||||
$_SERVER["PHP_AUTH_USER"],
|
||||
$_SERVER["PHP_AUTH_PW"],
|
||||
md5($_SERVER["PHP_AUTH_PW"]));
|
||||
exit;
|
||||
}
|
||||
|
||||
// common code to force that the user is authenticated
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
authenticate();
|
||||
}
|
||||
?>
|
Loading…
Reference in a new issue