/* ** 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"); @ @ @ @ @ @ azResult = db_query( "SELECT id, name, email, capabilities FROM user ORDER BY id"); for(i=0; azResult[i]; i+= 4){ @ @ @ if( azResult[i+2] && azResult[i+2][0] ){ char *zE = azResult[i+2]; @ } else { @ } @ } @
User ID   Permissions   In Real Life
if( g.okAdmin ){ @ } @ %h(azResult[i]) if( g.okAdmin ){ @ } @ %s(azResult[i+3])%h(azResult[i+1]) @ (%h(zE))%h(azResult[i+1])
@


@ Notes: @
    @
  1. The permission flags are as follows:

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

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

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

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

  8. } @
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?"); @
@

You are about to delete the user %h(zId) from @ the database. This is an irreversible operation.

@ @ @ @ @ @ @ @
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"); } @
@ @ @ if( zId ){ @ }else{ @ } @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ if( !higherUser ){ @ @ @ @ } @
User ID:%h(zId)
Full Name:
E-Mail:
Capabilities: @ Admin
@ Delete
@ Check-In
@ Read Wiki
@ Write Wiki
@ New Tkt
@ Check-Out
@ Password
@ Query
@ Read
if( g.okSetup ){ @ Setup
} @ Write @
Password:
  @     @
@

Notes:

@
    if( higherUser ){ @
  1. @ User %h(zId) has Setup privileges and you only have Admin privileges @ so you are not permitted to make changes to %h(zId). @

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

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

  6. @ }else{ @
  7. @ If the Check-out capability is specified then the user will be able @ to browse the %s(g.scm.zName) repository. @

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

  10. @ } @
  11. @ The Read and Write privileges give the user the ability @ to read and write tickets. The New Tkt capability means that @ the user is able to create new tickets. @

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

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

  16. @ @
  17. @ An Admin user can add other users, create new ticket report @ formats, and change system defaults. But only the Setup user @ is able to change the %h(g.scm.zName) repository to @ which this program is linked. @

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

  20. @ @
  21. @ The password for the "anonymous" user is used for anonymous @ %h(g.scm.zName) access. The recommended value for the anonymous password @ is "anonymous". @

  22. } @ 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; } }