/* ** Copyright (c) 2002 D. Richard Hipp ** ** 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 library; if not, write to the ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, ** Boston, MA 02111-1307, USA. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** Routines for handling user account */ #define _XOPEN_SOURCE #include #include "config.h" #include "user.h" /* ** WEBPAGE: /userlist */ void user_list(void){ char **azResult; int i; login_check_credentials(); if( !g.okWrite && g.isAnon ){ login_needed(); return; } common_standard_menu("userlist", 0); common_add_help_item("CvstracAdminUsers"); common_add_action_item("useredit", "Add User"); common_header("User List"); cgi_printf("\n" "\n" " \n" " \n" " \n" "\n"); azResult = db_query( "SELECT id, name, email, capabilities FROM user ORDER BY id"); for(i=0; azResult[i]; i+= 4){ cgi_printf("\n" "\n" "\n",azResult[i+3]); if( azResult[i+2] && azResult[i+2][0] ){ char *zE = azResult[i+2]; cgi_printf("\n",azResult[i+1],zE,zE); } else { cgi_printf("\n",azResult[i+1]); } cgi_printf("\n"); } cgi_printf("
User ID   Permissions   In Real Life
\n"); if( g.okAdmin ){ cgi_printf("\n",azResult[i]); } cgi_printf("%h\n",azResult[i]); if( g.okAdmin ){ cgi_printf("\n"); } cgi_printf("%s%h\n" " (%h)%h
\n" "


\n" "Notes:\n" "
    \n" "
  1. The permission flags are as follows:

    \n" "\n" "\n" " \n" "\n" " \n" "\n" " \n" "\n" "\n" "\n" "\n" " \n" "\n" "\n" "\n" "\n" "\n" "
    aAdmin: Create or delete users and ticket report formats
    dDelete: Erase anonymous wiki, tickets, and attachments
    iCheck-in: Add new code to the %h repository
    jRead-Wiki: View wiki pages
    kWiki: Create or modify wiki pages
    nNew: Create new tickets
    oCheck-out: Read code out of the %h repository
    pPassword: Change password
    qQuery: Create or edit report formats
    rRead: View tickets and change histories
    sSetup: Change CVSTrac options
    wWrite: Edit tickets
    \n" "

  2. \n" "\n" "
  3. \n" "If a user named \"anonymous\" exists, then anyone can access\n" "the server without having to log in. The permissions on the\n" "anonymous user determine the access rights for anyone who is not\n" "logged in.\n" "

  4. \n" "\n",g.scm.zName,g.scm.zName); if( !strcmp(g.scm.zSCM,"cvs") ){ cgi_printf("
  5. \n" "You must be using CVS version 1.11 or later in order to give users\n" "read-only access to the repository.\n" "With earlier versions of CVS, all users with check-out\n" "privileges also automatically get check-in privileges.\n" "

  6. \n" "\n" "
  7. \n" "Changing a users ID or password modifies the CVSROOT/passwd,\n" "CVSROOT/readers, and CVSROOT/writers files in the CVS\n" "repository, if those files have write permission turned on. Users\n" "IDs in CVSROOT/passwd that are unknown to CVSTrac are preserved.\n"); if( g.okSetup ){ cgi_printf("Use the \"Import CVS Users\" button on the \n" "user setup page\n" "to import CVS users into CVSTrac.\n"); } cgi_printf("

  8. \n"); } cgi_printf("
\n"); common_footer(); } /* ** WEBPAGE: /useredit */ void user_edit(void){ char **azResult; const char *zId, *zName, *zEMail, *zCap; char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap ; char *oak, *oad, *oaq; int doWrite; int higherUser = 0; /* True if user being edited is SETUP and the */ /* user doing the editing is ADMIN. Disallow editing */ /* Must have ADMIN privleges to access this page */ login_check_credentials(); if( !g.okAdmin ){ login_needed(); return; } /* Check to see if an ADMIN user is trying to edit a SETUP account. ** Don't allow that. */ zId = P("id"); if( zId && !g.okSetup ){ char *zOldCaps; zOldCaps = db_short_query( "SELECT capabilities FROM user WHERE id='%q'",zId); higherUser = zOldCaps && strchr(zOldCaps,'s'); } if( !higherUser ){ if( P("delete") ){ common_add_action_item("userlist", "Cancel"); common_header("Are You Sure?"); cgi_printf("
\n" "

You are about to delete the user %h from\n" "the database. This is an irreversible operation.

\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "
\n",zId,zId); common_footer(); return; }else if( P("can") ){ cgi_redirect("userlist"); return; } } /* If we have all the necessary information, write the new or ** modified user record. After writing the user record, redirect ** to the page that displays a list of users. */ doWrite = zId && zId[0] && cgi_all("nm","em","pw") && !higherUser; if( doWrite ){ const char *zOldPw; char zCap[20]; int i = 0; int aa = P("aa")!=0; int ad = P("ad")!=0; int ai = P("ai")!=0; int aj = P("aj")!=0; int ak = P("ak")!=0; int an = P("an")!=0; int ao = P("ao")!=0; int ap = P("ap")!=0; int aq = P("aq")!=0; int ar = P("ar")!=0; int as = g.okSetup && P("as")!=0; int aw = P("aw")!=0; if( as ) aa = 1; if( aa ) ai = aw = ap = 1; if( aw ) an = ar = 1; if( ai ) ao = 1; if( ak ) aj = 1; if( aa ){ zCap[i++] = 'a'; } if( ad ){ zCap[i++] = 'd'; } if( ai ){ zCap[i++] = 'i'; } if( aj ){ zCap[i++] = 'j'; } if( ak ){ zCap[i++] = 'k'; } if( an ){ zCap[i++] = 'n'; } if( ao ){ zCap[i++] = 'o'; } if( ap ){ zCap[i++] = 'p'; } if( aq ){ zCap[i++] = 'q'; } if( ar ){ zCap[i++] = 'r'; } if( as ){ zCap[i++] = 's'; } if( aw ){ zCap[i++] = 'w'; } zCap[i] = 0; zOldPw = db_short_query("SELECT passwd FROM user WHERE id='%q'", zId); db_execute("DELETE FROM user WHERE id='%q'", zId); if( !P("delete2") ){ const char *zPw = P("pw"); char zBuf[3]; if( zOldPw==0 ){ char zSeed[100]; const char *z; bprintf(zSeed,sizeof(zSeed),"%d%.20s",getpid(),zId); z = crypt(zSeed, "aa"); zBuf[0] = z[2]; zBuf[1] = z[3]; zBuf[2] = 0; zOldPw = zBuf; } db_execute( "INSERT INTO user(id,name,email,passwd,capabilities) " "VALUES('%q','%q','%q','%q','%s')", zId, P("nm"), P("em"), zPw[0] ? crypt(zPw, zOldPw) : zOldPw, zCap ); }else{ /* User was default assigned user id. Remove the default. */ db_execute( "DELETE FROM config WHERE " " name='assignto' AND value='%q'", zId); } /* ** The SCM subsystem may be able to replicate the user db somewhere... */ if( g.scm.pxUserWrite ) g.scm.pxUserWrite(P("delete2")!=0 ? zId : 0); cgi_redirect("userlist"); return; } /* Load the existing information about the user, if any */ zName = ""; zEMail = ""; zCap = ""; oaa = oad = oai = oaj = oak = oan = oao = oap = oaq = oar = oas = oaw = ""; if( zId ){ azResult = db_query( "SELECT name, email, capabilities FROM user WHERE id='%q'", zId ); if( azResult && azResult[0] ){ zName = azResult[0]; zEMail = azResult[1]; zCap = azResult[2]; if( strchr(zCap, 'a') ) oaa = " checked"; if( strchr(zCap, 'd') ) oad = " checked"; if( strchr(zCap, 'i') ) oai = " checked"; if( strchr(zCap, 'j') ) oaj = " checked"; if( strchr(zCap, 'k') ) oak = " checked"; if( strchr(zCap, 'n') ) oan = " checked"; if( strchr(zCap, 'o') ) oao = " checked"; if( strchr(zCap, 'p') ) oap = " checked"; if( strchr(zCap, 'q') ) oaq = " checked"; if( strchr(zCap, 'r') ) oar = " checked"; if( strchr(zCap, 's') ) oas = " checked"; if( strchr(zCap, 'w') ) oaw = " checked"; }else{ zId = 0; } } /* Begin generating the page */ common_standard_menu(0,0); common_add_help_item("CvstracAdminUsers"); common_add_action_item("userlist", "Cancel"); common_add_action_item(mprintf("useredit?delete=1&id=%t",zId), "Delete"); if( zId ){ common_header("Edit User %s", zId); }else{ common_header("Add New User"); } cgi_printf("
\n" "\n" "\n" " \n",g.zPath); if( zId ){ cgi_printf(" \n",zId,zId); }else{ cgi_printf(" \n"); } cgi_printf("\n" "\n" " \n" " \n" "\n" "\n" " \n" " \n" "\n" "\n" " \n" " \n" "\n" "\n" " \n" " \n" "\n",oaw); if( !higherUser ){ cgi_printf("\n" " \n" " \n" "\n"); } cgi_printf("
User ID:%h
Full Name:
E-Mail:
Capabilities:\n" " Admin
\n" " Delete
\n" " Check-In
\n" " Read Wiki
\n" " Write Wiki
\n" " New Tkt
\n" " Check-Out
\n" " Password
\n" " Query
\n" " Read
\n",zName,zEMail,oaa,oad,oai,oaj,oak,oan,oao,oap,oaq,oar); if( g.okSetup ){ cgi_printf(" Setup
\n",oas); } cgi_printf(" Write\n" "
Password:
 \n" "    \n" "
\n" "

Notes:

\n" "
    \n"); if( higherUser ){ cgi_printf("
  1. \n" "User %h has Setup privileges and you only have Admin privileges\n" "so you are not permitted to make changes to %h.\n" "

  2. \n" "\n",zId,zId); } if( g.scm.pxUserWrite!=0 && !strcmp("yes",db_config("write_cvs_passwd","yes")) ){ cgi_printf("
  3. \n" "If the Check-out capability is specified then\n" "the password entered here will be used to regenerate the\n" "CVSROOT/passwd file and will thus become the CVS password\n" "as well as the password for this server.\n" "

  4. \n" "\n" "
  5. \n" "The Check-in capability means that the user ID will be written\n" "into the CVSROOT/writers file and thus allow write access to\n" "the CVS repository.\n" "

  6. \n" "\n"); }else{ cgi_printf("
  7. \n" "If the Check-out capability is specified then the user will be able\n" "to browse the %s repository.\n" "

  8. \n" "\n" "
  9. \n" "The Check-in capability gives the user the ability to edit check-in\n" "messages.\n" "

  10. \n" "\n",g.scm.zName); } cgi_printf("
  11. \n" "The Read and Write privileges give the user the ability\n" "to read and write tickets. The New Tkt capability means that\n" "the user is able to create new tickets.\n" "

  12. \n" "\n" "
  13. \n" "The Delete privilege give the user the ability to erase\n" "wiki, tickets, and atttachments that have been added by anonymous\n" "users. This capability is intended for deletion of spam.\n" "

  14. \n" "\n" "
  15. \n" "The Query privilege allows the user to create or edit\n" "report formats by specifying appropriate SQL. Users can run \n" "existing reports without the Query privilege.\n" "

  16. \n" "\n" "
  17. \n" "An Admin user can add other users, create new ticket report\n" "formats, and change system defaults. But only the Setup user\n" "is able to change the %h repository to\n" "which this program is linked.\n" "

  18. \n" "\n",g.scm.zName); if( zId==0 || strcmp(zId,"anonymous")==0 ){ cgi_printf("
  19. \n" "No login is required for user \"anonymous\". The capabilities\n" "of this user are available to anyone without supplying a username or\n" "password. To disable anonymous access, make sure there is no user\n" "with an ID of anonymous.\n" "

  20. \n" "\n" "
  21. \n" "The password for the \"anonymous\" user is used for anonymous\n" "%h access. The recommended value for the anonymous password\n" "is \"anonymous\".\n" "

  22. \n",g.scm.zName); } cgi_printf("\n"); common_footer(); } /* ** Remove the newline from the end of a string. */ void remove_newline(char *z){ while( *z && *z!='\n' && *z!='\r' ){ z++; } if( *z ){ *z = 0; } }