- 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