implemented SIG membership control, Delete SIG, and the "shell" for the
System Administration menu; also added "Post & Go Topics" as an option for the post box in conferencing
This commit is contained in:
parent
e23de5dae6
commit
680b84b9d8
11
TODO
11
TODO
|
@ -2,19 +2,20 @@ Lots!
|
|||
|
||||
- Unimplemented functions on the SIG Administration page:
|
||||
Set SIG Features (sigadmin, command=F)
|
||||
Membership Control (sigadmin, command=M)
|
||||
Delete SIG (sigadmin, command=DEL)
|
||||
|
||||
- Implement SIG invitations ("Invite" button on the profile).
|
||||
|
||||
- Unimplemented functions in the system admin menu:
|
||||
Set Global Parameters
|
||||
View/Edit Banned Users
|
||||
User Account Management
|
||||
(More stuff needs to be added, I'm just not sure what.)
|
||||
|
||||
- Should we provide the sysadmin the ability to disable SIG creation for
|
||||
non-admin users? Maybe there needs to be a "global" set of levels that
|
||||
aren't hardcoded. Where do they get stored? The database? (Maybe the
|
||||
nice shiny new "globals" table?)
|
||||
|
||||
- There's no system admin functionality AT ALL. We need to have this stuff
|
||||
before we go live. (It plugs into the Administrative SIG features.)
|
||||
|
||||
- Unimplemented functions on the Top page:
|
||||
Customize Sideboxes
|
||||
|
||||
|
|
13
etc/web.xml
13
etc/web.xml
|
@ -77,6 +77,14 @@
|
|||
<servlet-class>com.silverwrist.venice.servlets.Account</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>systemadmin</servlet-name>
|
||||
<description>
|
||||
System administration operations.
|
||||
</description>
|
||||
<servlet-class>com.silverwrist.venice.servlets.SystemAdmin</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>settings</servlet-name>
|
||||
<description>
|
||||
|
@ -208,6 +216,11 @@
|
|||
<url-pattern>/account</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>systemadmin</servlet-name>
|
||||
<url-pattern>/sysadmin</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>settings</servlet-name>
|
||||
<url-pattern>/settings</url-pattern>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
# MySQL script for initializing the Venice database.
|
||||
# Written by Eric J. Bowersox <erbo@silcom.com>
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -427,6 +428,7 @@ INSERT INTO refaudit (type, descr) VALUES
|
|||
(209, 'Set SIG Members-Only Flag'),
|
||||
(210, 'Set SIG Join Key'),
|
||||
(211, 'Set SIG Security Levels'),
|
||||
(212, 'Delete SIG'),
|
||||
(301, 'Create New Conference'),
|
||||
(302, 'Set Conference Security Levels'),
|
||||
(303, 'Set Conference Name'),
|
||||
|
@ -1302,7 +1304,7 @@ INSERT INTO refsigftr (ftr_code, is_default, is_locked, is_hidden, require_read,
|
|||
symbol, name, applet) VALUES
|
||||
(0, 1, 1, 1, 0, 4900, 0, 'PROF', 'Profile', 'sigprofile'),
|
||||
(1, 1, 1, 1, 0, 5000, 57000, 'ADMN', 'Administration', 'sigadmin'),
|
||||
(2, 0, 1, 1, 0, 10000, 63000, 'SYSA', 'System Administration', 'TODO'),
|
||||
(2, 0, 1, 1, 0, 10000, 63000, 'SYSA', 'System Administration', 'sysadmin'),
|
||||
(3, 1, 0, 0, 1, 500, 0, 'CONF', 'Conferences', 'confops');
|
||||
|
||||
##############################################################################
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Community System.
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
|
@ -20,4 +20,5 @@ package com.silverwrist.venice.core;
|
|||
public interface AdminOperations
|
||||
{
|
||||
// TODO: fill this in
|
||||
|
||||
} // end interface AdminOperations
|
||||
|
|
|
@ -153,4 +153,13 @@ public interface SIGContext extends SearchMode
|
|||
|
||||
public abstract boolean canManageConferences();
|
||||
|
||||
public abstract int getMemberLevel(int uid) throws DataException, AccessError;
|
||||
|
||||
public abstract void setMembership(int uid, int new_level)
|
||||
throws DataException, AccessError;
|
||||
|
||||
public abstract boolean canDelete();
|
||||
|
||||
public abstract void delete() throws DataException, AccessError;
|
||||
|
||||
} // end interface SIGContext
|
||||
|
|
|
@ -89,4 +89,8 @@ public interface UserContext extends SearchMode
|
|||
|
||||
public abstract List getConferenceHotlist() throws DataException;
|
||||
|
||||
public abstract boolean hasAdminAccess();
|
||||
|
||||
public abstract AdminOperations getAdminInterface() throws AccessError;
|
||||
|
||||
} // end interface UserContext
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
* (the "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.venice.core.impl;
|
||||
|
||||
import java.sql.*;
|
||||
import org.apache.log4j.*;
|
||||
import com.silverwrist.venice.core.*;
|
||||
import com.silverwrist.venice.db.*;
|
||||
|
||||
class AdminOperationsImpl implements AdminOperations
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Static data members
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private static Category logger = Category.getInstance(AdminOperationsImpl.class.getName());
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Attributes
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private EngineBackend engine; // the back end of the engine
|
||||
private UserBackend user; // the UserContext that created this object
|
||||
private DataPool datapool; // the data pool used by this object
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
AdminOperationsImpl(EngineBackend engine, UserBackend user, DataPool datapool)
|
||||
{
|
||||
this.engine = engine;
|
||||
this.user = user;
|
||||
this.datapool = datapool;
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface AdminOperations
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
} // end class AdminOperationsImpl
|
178
src/com/silverwrist/venice/core/impl/BackgroundSIGPurge.java
Normal file
178
src/com/silverwrist/venice/core/impl/BackgroundSIGPurge.java
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
* (the "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.venice.core.impl;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
import org.apache.log4j.*;
|
||||
import com.silverwrist.util.ParallelRunQueue;
|
||||
import com.silverwrist.venice.db.*;
|
||||
import com.silverwrist.venice.core.DataException;
|
||||
import com.silverwrist.venice.core.InternalStateError;
|
||||
|
||||
class BackgroundSIGPurge implements Runnable
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Static data members
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private static Category logger = Category.getInstance(BackgroundSIGPurge.class.getName());
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Attributes
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private DataPool datapool;
|
||||
private UserBackend user;
|
||||
private int sigid;
|
||||
private int num_confs;
|
||||
private int max_confid;
|
||||
private Hashtable conf_objects;
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BackgroundSIGPurge(DataPool datapool, UserBackend user, int sigid, int num_confs, int max_confid,
|
||||
Hashtable conf_objects)
|
||||
{
|
||||
this.datapool = datapool;
|
||||
this.user = user;
|
||||
this.sigid = sigid;
|
||||
this.num_confs = num_confs;
|
||||
this.max_confid = max_confid;
|
||||
this.conf_objects = conf_objects;
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface Runnable
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public void run()
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("BackgroundSIGPurge running on SIG #" + sigid);
|
||||
|
||||
Connection conn = null; // pooled database connection
|
||||
ParallelRunQueue rq = new ParallelRunQueue(2);
|
||||
|
||||
try
|
||||
{ // get a database connection from the pool
|
||||
conn = datapool.getConnection();
|
||||
Statement stmt = conn.createStatement();
|
||||
|
||||
// run some "lower priority" deletes
|
||||
stmt.executeUpdate("DELETE FROM contacts WHERE owner_sigid = " + sigid + ";");
|
||||
stmt.executeUpdate("DELETE FROM sigftrs WHERE sigid = " + sigid + ";");
|
||||
stmt.executeUpdate("DELETE FROM sigban WHERE sigid = " + sigid + ";");
|
||||
|
||||
// look up all conference IDs in this SIG
|
||||
int[] conf_ids = new int[num_confs];
|
||||
StringBuffer sql = new StringBuffer("SELECT confid FROM sigtoconf WHERE sigid = ");
|
||||
sql.append(sigid).append(" AND confid <= ").append(max_confid).append(" ORDER BY confid;");
|
||||
ResultSet rs = stmt.executeQuery(sql.toString());
|
||||
int conferences = 0;
|
||||
while (rs.next())
|
||||
conf_ids[conferences++] = rs.getInt(1);
|
||||
|
||||
for (int i=0; i<conferences; i++)
|
||||
{ // look to see if there's a conference SIG object first
|
||||
Integer key = new Integer(conf_ids[i]);
|
||||
ConferenceSIGContext confobj = (ConferenceSIGContext)(conf_objects.get(key));
|
||||
if (confobj!=null)
|
||||
{ // OK, there's an object - do the delete internally and release the object
|
||||
conf_objects.remove(key);
|
||||
confobj.delete(user);
|
||||
confobj.rd_release();
|
||||
|
||||
} // end if
|
||||
else
|
||||
{ // we need to manually remove the conference ourselves
|
||||
boolean delete_core = true;
|
||||
|
||||
// see if conference is linked to other SIGs - will determine whether we do the core purge
|
||||
// routine
|
||||
sql.setLength(0);
|
||||
sql.append("SELECT sigid FROM sigtoconf WHERE confid = ").append(key).append(" AND sigid <> ");
|
||||
sql.append(sigid).append(" LIMIT 1;");
|
||||
rs = stmt.executeQuery(sql.toString());
|
||||
if (rs.next())
|
||||
delete_core = false;
|
||||
|
||||
// delete the sigtoconf record
|
||||
sql.setLength(0);
|
||||
sql.append("DELETE FROM sigtoconf WHERE sigid = ").append(sigid).append(" AND confid = ");
|
||||
sql.append(key).append(';');
|
||||
|
||||
if (delete_core)
|
||||
{ // OK, we officially need to delete the whole core now...purge from the two important
|
||||
// tables first
|
||||
stmt.executeUpdate("DELETE FROM confs WHERE confid = " + key + ";");
|
||||
stmt.executeUpdate("DELETE FROM confalias WHERE confid = " + key + ";");
|
||||
|
||||
// determine the number of topics in this conference, and the maximum topic ID, and use
|
||||
// that information to queue up the conference deletion
|
||||
sql.setLength(0);
|
||||
sql.append("SELECT COUNT(*), MAX(topicid) FROM topics WHERE confid = ").append(key).append(';');
|
||||
rs = stmt.executeQuery(sql.toString());
|
||||
if (!(rs.next()))
|
||||
throw new InternalStateError("BackgroundSIGPurge.run screwup on conference SELECT");
|
||||
rq.queue(new BackgroundConferencePurge(datapool,key.intValue(),rs.getInt(1),rs.getInt(2)));
|
||||
|
||||
} // end if (have to delete conference data)
|
||||
|
||||
} // end else (deleting conference data manually)
|
||||
|
||||
} // end for
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("BackgroundSIGPurge basic delete complete for sig #" + sigid);
|
||||
|
||||
} // end try
|
||||
catch (SQLException e)
|
||||
{ // on an error, just die
|
||||
logger.error("BackgroundSIGPurge FATAL EXCEPTION purging #" + sigid + ": " + e.getMessage(),e);
|
||||
return;
|
||||
|
||||
} // end catch
|
||||
catch (DataException de)
|
||||
{ // on an error, just die
|
||||
logger.error("BackgroundSIGPurge FATAL EXCEPTION purging #" + sigid + ": " + de.getMessage(),de);
|
||||
return;
|
||||
|
||||
} // end catch
|
||||
finally
|
||||
{ // make sure we release the connection before we go
|
||||
if (conn!=null)
|
||||
datapool.releaseConnection(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
rq.run(); // now run the parallel queue to finish processing
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("BackgroundSIGPurge COMPLETE for sig #" + sigid);
|
||||
|
||||
} // end run
|
||||
|
||||
} // end class BackgroundSIGPurge
|
|
@ -1154,7 +1154,7 @@ class ConferenceCoreData implements ConferenceData
|
|||
|
||||
} // end canDeleteConference
|
||||
|
||||
public synchronized void delete(SIGBackend sig) throws DataException
|
||||
public synchronized void delete(UserBackend user, int the_sigid) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This conference has been deleted.");
|
||||
|
@ -1208,7 +1208,7 @@ class ConferenceCoreData implements ConferenceData
|
|||
} // end finally
|
||||
|
||||
// create an audit record indicating we were successful
|
||||
ar = new AuditRecord(AuditRecord.DELETE_CONF,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
|
||||
ar = new AuditRecord(AuditRecord.DELETE_CONF,user.realUID(),user.userRemoteAddress(),the_sigid,
|
||||
"confid=" + confid);
|
||||
|
||||
} // end try
|
||||
|
|
|
@ -100,6 +100,6 @@ public interface ConferenceData extends ReferencedData
|
|||
|
||||
public abstract boolean canDeleteConference(int level);
|
||||
|
||||
public abstract void delete(SIGBackend sig) throws DataException;
|
||||
public abstract void delete(UserBackend user, int the_sigid) throws DataException;
|
||||
|
||||
} // end interface ConferenceData
|
||||
|
|
|
@ -106,6 +106,6 @@ public interface ConferenceSIGContext extends ReferencedData
|
|||
|
||||
public abstract boolean canDeleteConference(int level);
|
||||
|
||||
public abstract void delete(SIGBackend sig) throws DataException;
|
||||
public abstract void delete(UserBackend user) throws DataException;
|
||||
|
||||
} // end interface ConferenceSIGContext
|
||||
|
|
|
@ -769,7 +769,7 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
|
|||
|
||||
} // end canDeleteConference
|
||||
|
||||
public void delete(SIGBackend sig) throws DataException
|
||||
public void delete(UserBackend user) throws DataException
|
||||
{
|
||||
ConferenceData c = getConferenceData();
|
||||
Connection conn = null;
|
||||
|
@ -782,7 +782,7 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
|
|||
|
||||
// see if we have to delete the core object as well
|
||||
StringBuffer sql = new StringBuffer("SELECT sigid FROM sigtoconf WHERE confid = ");
|
||||
sql.append(confid).append(" AND sigid <> ").append(this.sig.realSIGID()).append(" LIMIT 1;");
|
||||
sql.append(confid).append(" AND sigid <> ").append(sig.realSIGID()).append(" LIMIT 1;");
|
||||
ResultSet rs = stmt.executeQuery(sql.toString());
|
||||
if (rs.next())
|
||||
delete_core = false; // we don't delete the core yet
|
||||
|
@ -790,7 +790,7 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
|
|||
// remove the row that links this conference to this SIG
|
||||
sql.setLength(0);
|
||||
sql.append("DELETE FROM sigtoconf WHERE confid = ").append(confid).append(" AND sigid = ");
|
||||
sql.append(this.sig.realSIGID()).append(';');
|
||||
sql.append(sig.realSIGID()).append(';');
|
||||
stmt.executeUpdate(sql.toString());
|
||||
|
||||
// record that we've been deleted
|
||||
|
@ -816,7 +816,7 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
|
|||
|
||||
if (delete_core)
|
||||
{ // the conference is not linked to any other SIGs - we need to delete the core as well
|
||||
c.delete(sig);
|
||||
c.delete(user,sig.realSIGID());
|
||||
engine.detachConferenceDataObject(confid);
|
||||
|
||||
} // end if
|
||||
|
|
|
@ -69,6 +69,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
private boolean public_sig; // is this a public SIG?
|
||||
private BitSet features; // set of available features
|
||||
private Hashtable conf_objects = new Hashtable(); // holder for ConferenceSIGContextImpl objects
|
||||
private boolean deleted = false; // has this SIG been deleted?
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
|
@ -340,8 +341,10 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
} // end getLastUpdateDate
|
||||
|
||||
public void testMembership(int level, boolean is_member) throws AccessError
|
||||
public void testMembership(int level, boolean is_member) throws DataException, AccessError
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
if (Capability.exemptFromMembershipRequirement(level))
|
||||
return;
|
||||
if (members_only && !is_member)
|
||||
|
@ -355,6 +358,8 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public boolean checkMembership(int level, boolean is_member)
|
||||
{
|
||||
if (deleted)
|
||||
return false;
|
||||
if (Capability.exemptFromMembershipRequirement(level))
|
||||
return true;
|
||||
return !members_only || is_member;
|
||||
|
@ -363,31 +368,39 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public boolean canReadSIGSubObjects(int level)
|
||||
{
|
||||
if (deleted)
|
||||
return false;
|
||||
return (level>=read_level);
|
||||
|
||||
} // end canReadSIGSubObjects
|
||||
|
||||
public boolean canModifySIGProfile(int level)
|
||||
{
|
||||
if (deleted)
|
||||
return false;
|
||||
return (level>=write_level);
|
||||
|
||||
} // end canModifySIGProfile
|
||||
|
||||
public boolean canCreateSIGSubObjects(int level)
|
||||
{
|
||||
if (deleted)
|
||||
return false;
|
||||
return (level>=create_level);
|
||||
|
||||
} // end canCreateSIGSubObjects
|
||||
|
||||
public boolean canDeleteSIG(int level)
|
||||
{
|
||||
if (deleted)
|
||||
return false;
|
||||
return (level>=delete_level);
|
||||
|
||||
} // end canDeleteSIG
|
||||
|
||||
public boolean canJoinSIG(int uid, int level)
|
||||
{
|
||||
if (level<join_level)
|
||||
if (deleted || (level<join_level))
|
||||
return false; // rejected on a level basis
|
||||
|
||||
Connection conn = null; // database connection
|
||||
|
@ -423,6 +436,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void putContactInfo(UserBackend user, ContactInfo ci) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
|
||||
|
@ -488,6 +504,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void putFeatureSet(UserBackend user, BitSet set) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
|
||||
|
@ -583,6 +602,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void setName(UserBackend user, String name) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
|
||||
|
@ -629,6 +651,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void setAlias(UserBackend user, String alias) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
|
||||
|
@ -676,6 +701,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void setCategoryID(UserBackend user, int catid) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
|
||||
|
@ -723,6 +751,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void setSynopsis(String synopsis) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
|
||||
try
|
||||
|
@ -755,6 +786,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void setLanguage(String language) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
|
||||
try
|
||||
|
@ -787,6 +821,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void setRules(String rules) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
|
||||
try
|
||||
|
@ -819,6 +856,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void touch() throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
return; // no need to touch anything
|
||||
|
||||
Connection conn = null; // database connection
|
||||
|
||||
try
|
||||
|
@ -862,6 +902,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
public synchronized void setHideFlags(UserBackend user, boolean directory, boolean search)
|
||||
throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
|
||||
|
@ -917,6 +960,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void setMembersOnly(UserBackend user, boolean flag) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
|
||||
|
@ -970,6 +1016,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void setInitialFeatureIndex(short ndx) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
|
||||
try
|
||||
|
@ -1002,6 +1051,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public String getJoinKey() throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
|
||||
try
|
||||
|
@ -1038,6 +1090,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized void setJoinKey(UserBackend user, String key) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
|
||||
|
@ -1115,6 +1170,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
public synchronized void setSecurityLevels(UserBackend user, int read, int write, int create, int delete,
|
||||
int join) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
|
||||
|
@ -1182,6 +1240,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
public synchronized void setMembership(UserBackend user, int uid, int grant_level, boolean locked,
|
||||
boolean hidden) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // successful audit record
|
||||
|
||||
|
@ -1274,6 +1335,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public int getMemberCount(boolean include_hidden) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // database connection
|
||||
|
||||
try
|
||||
|
@ -1311,6 +1375,8 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public boolean isFeaturePresent(String symbol)
|
||||
{
|
||||
if (deleted)
|
||||
return false;
|
||||
int ndx = engine.getFeatureIndexBySymbol(symbol);
|
||||
if (ndx>=0)
|
||||
return features.get(ndx);
|
||||
|
@ -1321,6 +1387,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public synchronized ConferenceSIGContext getConferenceDataObject(int confid) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("getConferenceDataObject(" + confid + ")...");
|
||||
|
||||
|
@ -1367,6 +1436,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
public ConferenceSIGContext createConference(SIGBackend sig, String name, String alias, String description,
|
||||
boolean pvt, boolean hide_list) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
ReturnConfSeq rcs = ConferenceCoreData.createConference(engine,sig,datapool,name,alias,description,
|
||||
pvt,hide_list,host_uid);
|
||||
ConferenceData cdata = rcs.getConference();
|
||||
|
@ -1399,6 +1471,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
public List searchForMembers(int field, int mode, String term, int offset, int count,
|
||||
boolean include_hidden) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Member search: SIG = " + sigid + ", field = " + field + ", mode = " + mode + ", term '"
|
||||
+ term + "', offset = " + offset + ", count = " + count);
|
||||
|
@ -1501,6 +1576,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
public int getSearchMemberCount(int field, int mode, String term, boolean include_hidden)
|
||||
throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("User search: SIG = " + sigid + ", field = " + field + ", mode = " + mode + ", term '"
|
||||
+ term + "'");
|
||||
|
@ -1590,6 +1668,9 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
public List getMemberList(boolean include_hidden) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Member list: SIG = " + sigid);
|
||||
|
||||
|
@ -1645,6 +1726,139 @@ class SIGCoreData implements SIGData, SIGDataBackend
|
|||
|
||||
} // end getMemberList
|
||||
|
||||
public int getMemberLevel(int uid) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Member level: SIG = " + sigid + ", user = " + uid);
|
||||
|
||||
Connection conn = null; // pooled database connection
|
||||
|
||||
try
|
||||
{ // get a database connection
|
||||
conn = datapool.getConnection();
|
||||
Statement stmt = conn.createStatement();
|
||||
|
||||
// a relatively simple search
|
||||
StringBuffer sql = new StringBuffer("SELECT granted_lvl FROM sigmember WHERE sigid = ");
|
||||
sql.append(sigid).append(" AND uid = ").append(uid).append(';');
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("SQL: " + sql.toString());
|
||||
ResultSet rs = stmt.executeQuery(sql.toString());
|
||||
if (rs.next())
|
||||
return rs.getInt(1);
|
||||
else
|
||||
return -1;
|
||||
|
||||
} // end try
|
||||
catch (SQLException e)
|
||||
{ // turn SQLException into data exception
|
||||
logger.error("DB error reading member level: " + e.getMessage(),e);
|
||||
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
|
||||
|
||||
} // end catch
|
||||
finally
|
||||
{ // make sure we release the connection before we go
|
||||
if (conn!=null)
|
||||
datapool.releaseConnection(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
} // end getMemberLevel
|
||||
|
||||
public void delete(UserBackend user) throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Delete SIG: SIG = " + sigid);
|
||||
|
||||
Connection conn = null; // database connection
|
||||
AuditRecord ar = null; // audit record
|
||||
int conf_count, conf_max;
|
||||
|
||||
try
|
||||
{ // get a database connection
|
||||
conn = datapool.getConnection();
|
||||
Statement stmt = conn.createStatement();
|
||||
|
||||
// lock the tables we need to reference immediately
|
||||
stmt.executeUpdate("LOCK TABLES sigs WRITE, sigmember WRITE, sigtoconf READ;");
|
||||
try
|
||||
{ // first delete the SIG record itself
|
||||
stmt.executeUpdate("DELETE FROM sigs WHERE sigid = " + sigid + ";");
|
||||
|
||||
// now delete the members list
|
||||
stmt.executeUpdate("DELETE FROM sigmember WHERE sigid = " + sigid + ";");
|
||||
|
||||
// determine the number of conferences in this SIG, and the maximum conference ID
|
||||
ResultSet rs = stmt.executeQuery("SELECT COUNT(*), MAX(confid) FROM sigtoconf WHERE sigid = "
|
||||
+ sigid + ";");
|
||||
if (!(rs.next()))
|
||||
throw new InternalStateError("SIGCoreData.delete screwup on conference SELECT");
|
||||
conf_count = rs.getInt(1);
|
||||
conf_max = rs.getInt(2);
|
||||
|
||||
// record that we're now deleted
|
||||
created = null;
|
||||
last_access = null;
|
||||
last_update = null;
|
||||
contactid = -1;
|
||||
name = null;
|
||||
language = null;
|
||||
synopsis = null;
|
||||
rules = null;
|
||||
alias = null;
|
||||
deleted = true;
|
||||
|
||||
} // end try
|
||||
finally
|
||||
{ // make sure to unlock the tables before we go
|
||||
Statement ulk_stmt = conn.createStatement();
|
||||
ulk_stmt.executeUpdate("UNLOCK TABLES;");
|
||||
|
||||
} // end finally
|
||||
|
||||
// create an audit record indicating what happened
|
||||
ar = new AuditRecord(AuditRecord.DELETE_SIG,user.realUID(),user.userRemoteAddress(),sigid);
|
||||
|
||||
} // end try
|
||||
catch (SQLException e)
|
||||
{ // database error - this is a DataException
|
||||
logger.error("DB error deleting SIG: " + e.getMessage(),e);
|
||||
throw new DataException("unable to delete SIG: " + e.getMessage(),e);
|
||||
|
||||
} // end catch
|
||||
finally
|
||||
{ // make sure the connection is released before we go
|
||||
try
|
||||
{ // save off the audit record before we go, though
|
||||
if ((ar!=null) && (conn!=null))
|
||||
ar.store(conn);
|
||||
|
||||
} // end try
|
||||
catch (SQLException e)
|
||||
{ // we couldn't store the audit record!
|
||||
logger.error("DB error saving audit record: " + e.getMessage(),e);
|
||||
|
||||
} // end catch
|
||||
|
||||
if (conn!=null)
|
||||
datapool.releaseConnection(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
// Delete the rest of the gunk in the background; use another thread to do it.
|
||||
BackgroundSIGPurge purger = new BackgroundSIGPurge(datapool,user,sigid,conf_count,conf_max,conf_objects);
|
||||
Thread thrd = new Thread(purger);
|
||||
thrd.setPriority(Thread.NORM_PRIORITY-1);
|
||||
thrd.start();
|
||||
|
||||
} // end delete
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface SIGDataBackend
|
||||
*--------------------------------------------------------------------------------
|
||||
|
|
|
@ -52,7 +52,7 @@ public interface SIGData extends ReferencedData
|
|||
|
||||
public abstract Date getLastUpdateDate();
|
||||
|
||||
public abstract void testMembership(int level, boolean is_member) throws AccessError;
|
||||
public abstract void testMembership(int level, boolean is_member) throws DataException, AccessError;
|
||||
|
||||
public abstract boolean checkMembership(int level, boolean is_member);
|
||||
|
||||
|
@ -146,4 +146,8 @@ public interface SIGData extends ReferencedData
|
|||
|
||||
public abstract List getMemberList(boolean include_hidden) throws DataException;
|
||||
|
||||
public abstract int getMemberLevel(int uid) throws DataException;
|
||||
|
||||
public abstract void delete(UserBackend user) throws DataException;
|
||||
|
||||
} // end interface SIGData
|
||||
|
|
|
@ -80,6 +80,7 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
private boolean locked; // is our membership locked?
|
||||
private SIGSimpleDataCache cache; // cache object for name and alias
|
||||
private SIGData sigdata = null; // the actual SIG data
|
||||
private boolean deleted = false; // has this SIG been deleted?
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructors
|
||||
|
@ -174,6 +175,8 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
{
|
||||
if (sigdata==null)
|
||||
{ // attempt to load the SIGDataObject
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
sigdata = engine.getSIGDataObject(sigid);
|
||||
|
||||
// clear cache when we get the real sigdata
|
||||
|
@ -189,6 +192,8 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
{
|
||||
if (sigdata==null)
|
||||
{ // we need to load the SIGData...
|
||||
if (deleted)
|
||||
return null; // we're deleted
|
||||
try
|
||||
{ // attempt to load the SIGDataObject
|
||||
sigdata = engine.getSIGDataObject(sigid);
|
||||
|
@ -212,6 +217,9 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
|
||||
private void testConferenceAccess() throws DataException, AccessError
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
if (!(getSIGData().isFeaturePresent("CONF")))
|
||||
{ // the SIG doesn't use conferencing
|
||||
logger.error("the SIG doesn't use conferencing");
|
||||
|
@ -340,6 +348,8 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
|
||||
public CategoryDescriptor getCategory() throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
return new CategoryDescriptorImpl(datapool,getSIGData().getCategoryID(),
|
||||
Capability.hideHiddenCategories(user.realBaseLevel()));
|
||||
|
||||
|
@ -367,6 +377,9 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
|
||||
public UserProfile getHostProfile() throws DataException
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
Connection conn = null; // pooled database connection
|
||||
|
||||
try
|
||||
|
@ -942,6 +955,9 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
|
||||
public void join(String joinkey) throws DataException, AccessError
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
if (is_member)
|
||||
{ // we're already a member!
|
||||
logger.info("attempting to join SIG, but already a member");
|
||||
|
@ -986,6 +1002,9 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
|
||||
public void unjoin() throws DataException, AccessError
|
||||
{
|
||||
if (deleted)
|
||||
throw new DataException("This SIG has been deleted.");
|
||||
|
||||
if (!is_member)
|
||||
{ // we're already a member!
|
||||
logger.info("attempting to unjoin SIG, but not currently a member");
|
||||
|
@ -1016,13 +1035,13 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
|
||||
public boolean canUnjoin()
|
||||
{
|
||||
return is_member && !locked;
|
||||
return !deleted && is_member && !locked;
|
||||
|
||||
} // end canUnjoin
|
||||
|
||||
public boolean canJoin()
|
||||
{
|
||||
if (is_member)
|
||||
if (is_member || deleted)
|
||||
return false;
|
||||
SIGData sd = getSIGDataNE();
|
||||
if (sd!=null)
|
||||
|
@ -1138,6 +1157,70 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
|
|||
|
||||
} // end canManageConferences
|
||||
|
||||
public int getMemberLevel(int uid) throws DataException, AccessError
|
||||
{
|
||||
getSIGData().testMembership(level,is_member);
|
||||
|
||||
return getSIGData().getMemberLevel(uid);
|
||||
|
||||
} // end getMemberLevel
|
||||
|
||||
public void setMembership(int uid, int new_level) throws DataException, AccessError
|
||||
{
|
||||
getSIGData().testMembership(level,is_member);
|
||||
if (!(getSIGData().canModifySIGProfile(level)))
|
||||
{ // this user can't modify the SIG feature set
|
||||
logger.error("user not permitted to modify the SIG's membership");
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("(your level = " + level + ")");
|
||||
throw new AccessError("You are not permitted to modify the SIG's membership.");
|
||||
|
||||
} // end if
|
||||
|
||||
// actually set the data in the database
|
||||
getSIGData().setMembership(user,uid,new_level,false,false);
|
||||
|
||||
if (uid==user.realUID()) // and update our internal data store
|
||||
setMemberValues(new_level,(new_level>0),false);
|
||||
|
||||
} // end setMembership
|
||||
|
||||
public boolean canDelete()
|
||||
{
|
||||
SIGData sd = getSIGDataNE();
|
||||
if (sd==null)
|
||||
return false;
|
||||
if (!(sd.checkMembership(level,is_member)))
|
||||
return false;
|
||||
return sd.canDeleteSIG(level);
|
||||
|
||||
} // end canDelete
|
||||
|
||||
public void delete() throws DataException, AccessError
|
||||
{
|
||||
SIGData my_sig = getSIGData();
|
||||
my_sig.testMembership(level,is_member);
|
||||
if (!(my_sig.canDeleteSIG(level)))
|
||||
{ // no, repeat NO, way can we delete the SIG!
|
||||
logger.error("user not permitted to delete SIG");
|
||||
throw new AccessError("You are not permitted to delete this SIG.");
|
||||
|
||||
} // end if
|
||||
|
||||
// call the methods required to delete the SIG
|
||||
my_sig.delete(user);
|
||||
engine.detachSIGDataObject(sigid);
|
||||
|
||||
// flag that we've been deleted
|
||||
cache = null;
|
||||
deleted = true;
|
||||
|
||||
// detach our references from the lower-level object
|
||||
sigdata = null;
|
||||
my_sig.rd_release();
|
||||
|
||||
} // end delete
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface UserBackend
|
||||
*--------------------------------------------------------------------------------
|
||||
|
|
|
@ -868,6 +868,26 @@ class UserContextImpl implements UserContext, UserBackend
|
|||
|
||||
} // end getConferenceHotlist
|
||||
|
||||
public boolean hasAdminAccess()
|
||||
{
|
||||
return Capability.canAdministerSystem(level);
|
||||
|
||||
} // end hasAdminAccess
|
||||
|
||||
public AdminOperations getAdminInterface() throws AccessError
|
||||
{
|
||||
if (!(Capability.canAdministerSystem(level)))
|
||||
{ // you don't have access to get this!
|
||||
logger.error("user does not have access to do system admin stuff");
|
||||
throw new AccessError("You are not permitted to administer the server.");
|
||||
|
||||
} // end if
|
||||
|
||||
// create the return object
|
||||
return new AdminOperationsImpl(engine,this,datapool);
|
||||
|
||||
} // end getAdminInterface
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface UserBackend
|
||||
*--------------------------------------------------------------------------------
|
||||
|
|
|
@ -1176,10 +1176,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
|
|||
|
||||
while (rs.next())
|
||||
{ // add all the found users to the list
|
||||
UserFoundImpl ufi = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
|
||||
rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8));
|
||||
UserFound tmp = (UserFound)ufi;
|
||||
rc.add(tmp);
|
||||
UserFound uf = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
|
||||
rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8));
|
||||
rc.add(uf);
|
||||
|
||||
} // end while
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ public interface Audit
|
|||
public static final int SIG_MEMBERS_ONLY = 209;
|
||||
public static final int SIG_JOIN_KEY = 210;
|
||||
public static final int SIG_SECURITY = 211;
|
||||
public static final int DELETE_SIG = 212;
|
||||
|
||||
// Codes 301-400 - Conference events
|
||||
public static final int CREATE_CONF = 301;
|
||||
|
|
|
@ -97,4 +97,10 @@ public class Capability implements SecLevels
|
|||
|
||||
} // end hideHiddenConferences
|
||||
|
||||
public static boolean canAdministerSystem(int level)
|
||||
{
|
||||
return (level>=GLOBAL_ANYADMIN);
|
||||
|
||||
} // end canAdministerSystem
|
||||
|
||||
} // end class Capability
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Community System.
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
|
@ -66,6 +66,7 @@ public class Role implements Comparable, SecLevels
|
|||
private static Role not_in_list = null;
|
||||
private static Role no_access = null;
|
||||
private static Role unrestricted_user = null;
|
||||
private static Role sig_host = null;
|
||||
private static Vector global_low = null;
|
||||
private static Vector global_high = null;
|
||||
private static Vector sig_low = null;
|
||||
|
@ -142,7 +143,8 @@ public class Role implements Comparable, SecLevels
|
|||
sig_high = new Vector(3);
|
||||
sig_high.addElement(new Role(SIG_ANYADMIN,"Any SIG Administrator"));
|
||||
sig_high.addElement(new Role(SIG_COHOST,"SIG Co-Host"));
|
||||
sig_high.addElement(new Role(SIG_HOST,"SIG Host"));
|
||||
sig_host = new Role(SIG_HOST,"SIG Host");
|
||||
sig_high.addElement(sig_host);
|
||||
sig_high.trimToSize();
|
||||
|
||||
} // end if
|
||||
|
@ -282,6 +284,26 @@ public class Role implements Comparable, SecLevels
|
|||
|
||||
} // end getSIGJoinList
|
||||
|
||||
public static List getSIGMemberLevelChoices()
|
||||
{
|
||||
initAllSets();
|
||||
Vector rc = new Vector();
|
||||
rc.add(not_in_list);
|
||||
rc.addAll(global_low);
|
||||
rc.addAll(sig_low);
|
||||
rc.add(unrestricted_user);
|
||||
rc.addAll(sig_high);
|
||||
rc.remove(rc.size()-1);
|
||||
return new ReadOnlyVector(rc);
|
||||
|
||||
} // end getSIGMemberLevelChoices
|
||||
|
||||
public static Role getSIGHostRole()
|
||||
{
|
||||
return sig_host;
|
||||
|
||||
} // end getSIGHostRole
|
||||
|
||||
public static List getConferenceReadList()
|
||||
{
|
||||
initAllSets();
|
||||
|
|
|
@ -109,9 +109,11 @@ public class PostMessage extends VeniceServlet
|
|||
request.getParameter("next"),getPostNumber(request,on_error),
|
||||
yes.equals(request.getParameter("attach")));
|
||||
|
||||
if (isImageButtonClicked(request,"post") || isImageButtonClicked(request,"postnext"))
|
||||
if ( isImageButtonClicked(request,"post") || isImageButtonClicked(request,"postnext")
|
||||
|| isImageButtonClicked(request,"posttopics"))
|
||||
{ // post the message, and then either go back to the same topic or on to the next one
|
||||
boolean go_next = isImageButtonClicked(request,"postnext");
|
||||
boolean go_topics = isImageButtonClicked(request,"posttopics");
|
||||
int pn = getPostNumber(request,on_error);
|
||||
|
||||
try
|
||||
|
@ -124,6 +126,9 @@ public class PostMessage extends VeniceServlet
|
|||
// post the darn thing!
|
||||
TopicMessageContext msg = topic.postNewMessage(0,request.getParameter("pseud"),raw_postdata);
|
||||
|
||||
if (go_topics) // jump back to the topic list, puhleaze
|
||||
throw new RedirectResult("confdisp?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID());
|
||||
|
||||
short next;
|
||||
try
|
||||
{ // attempt to get the value of the "next topic" parameter
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package com.silverwrist.venice.servlets;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import org.apache.log4j.*;
|
||||
|
@ -33,6 +34,9 @@ public class SIGAdmin extends VeniceServlet
|
|||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private static final String DELETE_CONFIRM_ATTR = "servlets.SIGAdmin.delete.confirm";
|
||||
private static final String DELETE_CONFIRM_PARAM = "confirm";
|
||||
|
||||
private static Category logger = Category.getInstance(SIGAdmin.class.getName());
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
|
@ -94,7 +98,7 @@ public class SIGAdmin extends VeniceServlet
|
|||
|
||||
protected VeniceContent doVeniceGet(HttpServletRequest request, VeniceEngine engine,
|
||||
UserContext user, RenderData rdat)
|
||||
throws ServletException, IOException, VeniceServletResult
|
||||
throws ServletException, IOException, VeniceServletResult
|
||||
{
|
||||
// get the SIG context
|
||||
SIGContext sig = getSIGParameter(request,user,true,"top");
|
||||
|
@ -224,6 +228,76 @@ public class SIGAdmin extends VeniceServlet
|
|||
|
||||
} // end if ("T" command)
|
||||
|
||||
if (cmd.equals("M"))
|
||||
{ // "M" = Set Membership
|
||||
if (!(sig.canModifyProfile()))
|
||||
{ // no access - sorry man
|
||||
logger.error("tried to call up membership set screen without access...naughty naughty!");
|
||||
return new ErrorBox("Unauthorized","You do not have access to modify this SIG's membership.",on_error);
|
||||
|
||||
} // end else
|
||||
|
||||
try
|
||||
{ // display the conference member list!
|
||||
SIGMembership m = new SIGMembership(engine,sig);
|
||||
m.doSIGMemberList();
|
||||
setMyLocation(request,"sigadmin?sig=" + sig.getSIGID() + "&cmd=M");
|
||||
return m;
|
||||
|
||||
} // end try
|
||||
catch (DataException de)
|
||||
{ // something wrong in the database
|
||||
return new ErrorBox("Database Error","Database error listing SIG members: " + de.getMessage(),
|
||||
on_error);
|
||||
|
||||
} // end catch
|
||||
|
||||
} // end if ("M" command)
|
||||
|
||||
if (cmd.equals("DEL"))
|
||||
{ // "DEL" = "Delete SIG" (requires a confirmation)
|
||||
if (!(sig.canDelete()))
|
||||
{ // we can't delete the SIG, so what are we doing here?
|
||||
logger.error("you can't delete the SIG - not gonna do it, wouldn't be prudent");
|
||||
return new ErrorBox("Access Error","You do not have permission to delete this SIG.",on_error);
|
||||
|
||||
} // end if
|
||||
|
||||
if (ConfirmBox.isConfirmed(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM))
|
||||
{ // we are confirmed - delete the SIG!
|
||||
try
|
||||
{ // delete the SIG!
|
||||
sig.delete();
|
||||
|
||||
} // end try
|
||||
catch (DataException de)
|
||||
{ // something wrong in the database
|
||||
logger.error("Database error deleting SIG: " + de.getMessage(),de);
|
||||
return new ErrorBox("Database Error","Database error deleting SIG: " + de.getMessage(),on_error);
|
||||
|
||||
} // end catch
|
||||
catch (AccessError ae)
|
||||
{ // access error changing the SIG values
|
||||
logger.error("Access error deleting SIG: " + ae.getMessage(),ae);
|
||||
return new ErrorBox("Access Error",ae.getMessage(),on_error);
|
||||
|
||||
} // end catch
|
||||
|
||||
// the SIG is now GONE - there's noplace else to go but back to the Top page
|
||||
throw new RedirectResult("top");
|
||||
|
||||
} // end if
|
||||
else
|
||||
{ // throw up a confirm box to let the user think it over
|
||||
String message = "You are about to permanently delete the \"" + sig.getName() + "\" SIG, including "
|
||||
+ "all conferences and other resources it contains! Are you sure you want to do this?";
|
||||
return new ConfirmBox(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM,"Delete Conference",message,
|
||||
on_error + "&cmd=DEL",on_error);
|
||||
|
||||
} // end else
|
||||
|
||||
} // end if ("DEL" command)
|
||||
|
||||
// all unknown requests get turned into menu display requests
|
||||
if (!(sig.canAdministerSIG()))
|
||||
{ // no access - sorry buddy
|
||||
|
@ -316,6 +390,149 @@ public class SIGAdmin extends VeniceServlet
|
|||
|
||||
} // end if ("P" command)
|
||||
|
||||
if (cmd.equals("M"))
|
||||
{ // "M" = Modify SIG Membership
|
||||
on_error += "&cmd=M";
|
||||
setMyLocation(request,on_error);
|
||||
|
||||
if (!(sig.canModifyProfile()))
|
||||
{ // no access - sorry, dude
|
||||
logger.error("tried to call up SIG membership screen without access...naughty naughty!");
|
||||
return new ErrorBox("Unauthorized","You do not have access to modify this SIG's membership.",on_error);
|
||||
|
||||
} // end if
|
||||
|
||||
if (isImageButtonClicked(request,"update"))
|
||||
{ // the "update" command that changes all the security levels
|
||||
HashMap org_vals = new HashMap();
|
||||
HashMap new_vals = new HashMap();
|
||||
try
|
||||
{ // retrieve all parameters and filter them for the levels
|
||||
Enumeration p_names = request.getParameterNames();
|
||||
while (p_names.hasMoreElements())
|
||||
{ // examine each parameter name in turn
|
||||
String p_name = (String)(p_names.nextElement());
|
||||
if (p_name.startsWith("zxcur_"))
|
||||
{ // this is a current value (from a hidden field)
|
||||
int uid = Integer.parseInt(p_name.substring(6));
|
||||
int level = Integer.parseInt(request.getParameter(p_name));
|
||||
org_vals.put(new Integer(uid),new Integer(level));
|
||||
|
||||
} // end if
|
||||
else if (p_name.startsWith("zxnew_"))
|
||||
{ // this is a new value (from a dropdown list box)
|
||||
int uid = Integer.parseInt(p_name.substring(6));
|
||||
int level = Integer.parseInt(request.getParameter(p_name));
|
||||
new_vals.put(new Integer(uid),new Integer(level));
|
||||
|
||||
} // end else if
|
||||
|
||||
} // end while
|
||||
|
||||
if (org_vals.size()!=new_vals.size())
|
||||
{ // we read the wrong number of parameters - this is bad
|
||||
logger.error("level parameters mismatch (" + org_vals.size() + " old, " + new_vals.size()
|
||||
+ " new)");
|
||||
return new ErrorBox(null,"Invalid parameters.",on_error);
|
||||
|
||||
} // end if
|
||||
|
||||
} // end try
|
||||
catch (NumberFormatException nfe)
|
||||
{ // error converting the parameters
|
||||
logger.error("got number format exception parsing a level parameter");
|
||||
return new ErrorBox(null,"Invalid parameter conversion.",on_error);
|
||||
|
||||
} // end catch
|
||||
|
||||
try
|
||||
{ // loop through the hashmaps and set the value
|
||||
Iterator it = org_vals.keySet().iterator();
|
||||
while (it.hasNext())
|
||||
{ // extract the UID, old level, and new level
|
||||
Integer uid = (Integer)(it.next());
|
||||
Integer org_level = (Integer)(org_vals.get(uid));
|
||||
Integer new_level = (Integer)(new_vals.get(uid));
|
||||
if (new_level==null)
|
||||
{ // whoops
|
||||
logger.error("new SIG level not found for uid " + uid.intValue());
|
||||
return new ErrorBox(null,"Invalid new level parameter.",on_error);
|
||||
|
||||
} // end if
|
||||
|
||||
int new_level_x = new_level.intValue();
|
||||
if (new_level_x==0)
|
||||
new_level_x = -1;
|
||||
|
||||
// call down to set the membership level
|
||||
if (org_level.intValue()!=new_level_x)
|
||||
{ // we need to reset the SIG membership
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("resetting SIG member level for uid " + uid.intValue() + "(old = "
|
||||
+ org_level.intValue() + ", new = " + new_level_x + ")");
|
||||
sig.setMembership(uid.intValue(),new_level_x);
|
||||
|
||||
} // end if
|
||||
|
||||
} // end while
|
||||
|
||||
} // end try
|
||||
catch (AccessError ae)
|
||||
{ // some sort of access error - display an error dialog
|
||||
logger.error("AccessError on sig.setMembership: " + ae.getMessage(),ae);
|
||||
return new ErrorBox("Access Error",ae.getMessage(),on_error);
|
||||
|
||||
} // end catch
|
||||
catch (DataException de)
|
||||
{ // database error creating the conference
|
||||
logger.error("DataException on sig.setMembership: " + de.getMessage(),de);
|
||||
return new ErrorBox("Database Error","Database error setting memberships: " + de.getMessage(),
|
||||
on_error);
|
||||
|
||||
} // end catch
|
||||
|
||||
// trap back to the SIG membership display
|
||||
throw new RedirectResult(on_error);
|
||||
|
||||
} // end if ("update" clicked)
|
||||
|
||||
if ( isImageButtonClicked(request,"search") || isImageButtonClicked(request,"previous")
|
||||
|| isImageButtonClicked(request,"next"))
|
||||
{ // create the new dialog box
|
||||
SIGMembership m = new SIGMembership(engine,sig);
|
||||
|
||||
try
|
||||
{ // perform the search!
|
||||
m.doSearch(request);
|
||||
|
||||
} // end try
|
||||
catch (ValidationException ve)
|
||||
{ // validation error - throw it back to the user
|
||||
return new ErrorBox(null,ve.getMessage() + " Please try again.",on_error);
|
||||
|
||||
} // end catch
|
||||
catch (AccessError ae)
|
||||
{ // some sort of access error - display an error dialog
|
||||
return new ErrorBox("Access Error",ae.getMessage(),on_error);
|
||||
|
||||
} // end catch
|
||||
catch (DataException de)
|
||||
{ // database error creating the conference
|
||||
return new ErrorBox("Database Error","Database error searching for users: " + de.getMessage(),
|
||||
on_error);
|
||||
|
||||
} // end catch
|
||||
|
||||
return m;
|
||||
|
||||
} // end if (search function clicked)
|
||||
|
||||
// we don't know what button was pressed
|
||||
logger.error("no known button click on SIGAdmin.doPost, cmd=M");
|
||||
return new ErrorBox("Internal Error","Unknown command button pressed",on_error);
|
||||
|
||||
} // end if ("M" command)
|
||||
|
||||
// on unknown command, redirect to the GET function
|
||||
return doVeniceGet(request,engine,user,rdat);
|
||||
|
||||
|
|
95
src/com/silverwrist/venice/servlets/SystemAdmin.java
Normal file
95
src/com/silverwrist/venice/servlets/SystemAdmin.java
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
* (the "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.venice.servlets;
|
||||
|
||||
import java.io.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import org.apache.log4j.*;
|
||||
import com.silverwrist.venice.core.*;
|
||||
import com.silverwrist.venice.servlets.format.*;
|
||||
|
||||
public class SystemAdmin extends VeniceServlet
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Static data members
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private static Category logger = Category.getInstance(SIGAdmin.class.getName());
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Internal functions
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private SystemAdminTop makeSystemAdminTop() throws ServletException
|
||||
{
|
||||
final String desired_name = "SystemAdminTop";
|
||||
MenuPanelCache cache = MenuPanelCache.getMenuPanelCache(getServletContext());
|
||||
|
||||
if (!(cache.isCached(desired_name)))
|
||||
{ // create a template and save it off
|
||||
SystemAdminTop template = new SystemAdminTop();
|
||||
cache.saveTemplate(template);
|
||||
|
||||
} // end if
|
||||
|
||||
// return a new copy
|
||||
return (SystemAdminTop)(cache.getNewMenuPanel(desired_name));
|
||||
|
||||
} // end makeSystemAdminTop
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Overrides from class HttpServlet
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public String getServletInfo()
|
||||
{
|
||||
String rc = "SystemAdmin servlet - Administrative functions for the entire system\n"
|
||||
+ "Part of the Venice Web Communities System\n";
|
||||
return rc;
|
||||
|
||||
} // end getServletInfo
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Overrides from class VeniceServlet
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
protected VeniceContent doVeniceGet(HttpServletRequest request, VeniceEngine engine,
|
||||
UserContext user, RenderData rdat)
|
||||
throws ServletException, IOException, VeniceServletResult
|
||||
{
|
||||
// decide what to do based on the "cmd" parameter
|
||||
String cmd = getStandardCommandParam(request);
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("SystemAdmin/doGet command value = " + cmd);
|
||||
|
||||
// TODO: command handling
|
||||
|
||||
if (!(user.hasAdminAccess()))
|
||||
return new ErrorBox("Access Error","You do not have permission to administer the system.",null);
|
||||
|
||||
setMyLocation(request,"sysadmin");
|
||||
return makeSystemAdminTop();
|
||||
|
||||
} // end doVeniceGet
|
||||
|
||||
} // end class SystemAdmin
|
|
@ -21,6 +21,7 @@ import java.io.*;
|
|||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import com.silverwrist.util.StringUtil;
|
||||
import com.silverwrist.venice.ValidationException;
|
||||
import com.silverwrist.venice.security.Role;
|
||||
import com.silverwrist.venice.core.*;
|
||||
|
@ -326,7 +327,7 @@ public class ConferenceMembership implements JSPRender, SearchMode
|
|||
out.write("<OPTION VALUE=\"" + r.getLevel() + "\"");
|
||||
if (r.getLevel()==cur_level)
|
||||
out.write(" SELECTED");
|
||||
out.write(">" + r.getName() + "</OPTION>\n");
|
||||
out.write(">" + StringUtil.encodeHTML(r.getName()) + "</OPTION>\n");
|
||||
|
||||
} // end while
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Community System.
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Community System.
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
|
|
333
src/com/silverwrist/venice/servlets/format/SIGMembership.java
Normal file
333
src/com/silverwrist/venice/servlets/format/SIGMembership.java
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
* (the "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.venice.servlets.format;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import com.silverwrist.util.StringUtil;
|
||||
import com.silverwrist.venice.ValidationException;
|
||||
import com.silverwrist.venice.security.Role;
|
||||
import com.silverwrist.venice.core.*;
|
||||
|
||||
public class SIGMembership implements JSPRender, SearchMode
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Static data members
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Attribute name for request attribute
|
||||
protected static final String ATTR_NAME = "com.silverwrist.venice.content.ConferenceMembership";
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Attributes
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private VeniceEngine engine; // reference to the engine
|
||||
private SIGContext sig; // the SIG we're in
|
||||
private List display_list = null; // list of members to display
|
||||
private boolean sig_members = false; // is this a list of SIG members?
|
||||
private int field = -1; // search field
|
||||
private int mode = -1; // search mode
|
||||
private String term = null; // search term
|
||||
private int offset = 0; // search result offset
|
||||
private int find_count = -1; // search results count
|
||||
private List role_choices; // the list of security roles
|
||||
private Role role_sig_host; // the "SIG Host" security role
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructors
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public SIGMembership(VeniceEngine engine, SIGContext sig)
|
||||
{
|
||||
this.engine = engine;
|
||||
this.sig = sig;
|
||||
this.role_choices = Role.getSIGMemberLevelChoices();
|
||||
this.role_sig_host = Role.getSIGHostRole();
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Internal functions
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private static int getParamInt(ServletRequest request, String name, int default_val)
|
||||
{
|
||||
String str = request.getParameter(name);
|
||||
if (str==null)
|
||||
return -1;
|
||||
|
||||
try
|
||||
{ // parse the integer value
|
||||
return Integer.parseInt(str);
|
||||
|
||||
} // end try
|
||||
catch (NumberFormatException nfe)
|
||||
{ // in case of conversion error, return default
|
||||
return default_val;
|
||||
|
||||
} // end catch
|
||||
|
||||
} // end getParamInt
|
||||
|
||||
private static boolean isImageButtonClicked(ServletRequest request, String name)
|
||||
{
|
||||
String val = request.getParameter(name + ".x");
|
||||
return (val!=null);
|
||||
|
||||
} // end isImageButtonClicked
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External static functions
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public static SIGMembership retrieve(ServletRequest request)
|
||||
{
|
||||
return (SIGMembership)(request.getAttribute(ATTR_NAME));
|
||||
|
||||
} // end retrieve
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface VeniceContent
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public String getPageTitle(RenderData rdat)
|
||||
{
|
||||
return "Membership in SIG " + sig.getName();
|
||||
|
||||
} // end getPageTitle
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface JSPRender
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public void store(ServletRequest request)
|
||||
{
|
||||
request.setAttribute(ATTR_NAME,this);
|
||||
|
||||
} // end store
|
||||
|
||||
public String getTargetJSPName()
|
||||
{
|
||||
return "sig_member.jsp";
|
||||
|
||||
} // end getTargetJSPName
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public void doSIGMemberList() throws DataException
|
||||
{
|
||||
this.display_list = sig.getMemberList();
|
||||
this.sig_members = true;
|
||||
this.term = "";
|
||||
|
||||
} // end doSIGMemberList
|
||||
|
||||
public void doSearch(ServletRequest request) throws ValidationException, DataException, AccessError
|
||||
{
|
||||
// Validate the search field parameter.
|
||||
field = getParamInt(request,"field",FIELD_USER_NAME);
|
||||
if ( (field!=FIELD_USER_NAME) && (field!=FIELD_USER_DESCRIPTION) && (field!=FIELD_USER_GIVEN_NAME)
|
||||
&& (field!=FIELD_USER_FAMILY_NAME))
|
||||
throw new ValidationException("The field search parameter is not valid.");
|
||||
|
||||
// Validate the search mode parameter.
|
||||
mode = getParamInt(request,"mode",SEARCH_PREFIX);
|
||||
if ((mode!=SEARCH_PREFIX) && (mode!=SEARCH_SUBSTRING) && (mode!=SEARCH_REGEXP))
|
||||
throw new ValidationException("The search mode parameter is not valid.");
|
||||
|
||||
// Retrieve the search term parameter.
|
||||
term = request.getParameter("term");
|
||||
if (term==null)
|
||||
term = "";
|
||||
|
||||
// Retrieve the offset and find count parameters.
|
||||
offset = getParamInt(request,"ofs",0);
|
||||
find_count = getParamInt(request,"fcount",-1);
|
||||
|
||||
// Adjust the search return offset based on the command button click.
|
||||
int count = getNumResultsDisplayed();
|
||||
if (isImageButtonClicked(request,"search"))
|
||||
offset = 0;
|
||||
else if (isImageButtonClicked(request,"previous"))
|
||||
{ // adjust the offset in the reverse direction
|
||||
offset -= count;
|
||||
if (offset<0)
|
||||
offset = 0;
|
||||
|
||||
} // end else if
|
||||
else if (isImageButtonClicked(request,"next"))
|
||||
offset += count; // go forwards instead
|
||||
else
|
||||
throw new ValidationException("Unable to determine what action triggered the form.");
|
||||
|
||||
// Perform the search!
|
||||
List intermediate = engine.searchForUsers(field,mode,term,offset,count);
|
||||
if (find_count<0)
|
||||
find_count = engine.getSearchUserCount(field,mode,term);
|
||||
|
||||
// Create the real display list by getting the SIG security levels.
|
||||
Iterator it = intermediate.iterator();
|
||||
Vector rc = new Vector(count+1);
|
||||
while (it.hasNext())
|
||||
{ // loop around and find the member level of every one
|
||||
UserFound uf = (UserFound)(it.next());
|
||||
int new_level = sig.getMemberLevel(uf.getUID());
|
||||
if (new_level==-1)
|
||||
new_level = 0;
|
||||
rc.add(uf.createNewLevel(new_level));
|
||||
|
||||
} // end while
|
||||
|
||||
display_list = rc; // save display list for display
|
||||
|
||||
} // end doSearch
|
||||
|
||||
public int getSIGID()
|
||||
{
|
||||
return sig.getSIGID();
|
||||
|
||||
} // end getSIGID
|
||||
|
||||
public String getSIGName()
|
||||
{
|
||||
return sig.getName();
|
||||
|
||||
} // end getSIGName
|
||||
|
||||
public String getLocator()
|
||||
{
|
||||
return "sig=" + sig.getSIGID();
|
||||
|
||||
} // end getLocator
|
||||
|
||||
public boolean displayList()
|
||||
{
|
||||
if ((display_list==null) || (display_list.size()==0))
|
||||
return false;
|
||||
if (sig_members && (display_list.size()>engine.getMaxNumSIGMembersDisplay()))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
} // end displayList
|
||||
|
||||
public boolean isSIGMemberList()
|
||||
{
|
||||
return sig_members;
|
||||
|
||||
} // end isSIGMemberList
|
||||
|
||||
public int getSearchField()
|
||||
{
|
||||
return field;
|
||||
|
||||
} // end getSearchField
|
||||
|
||||
public int getSearchMode()
|
||||
{
|
||||
return mode;
|
||||
|
||||
} // end getSearchMode
|
||||
|
||||
public boolean searchFieldIs(int value)
|
||||
{
|
||||
return (field==value);
|
||||
|
||||
} // end searchFieldIs
|
||||
|
||||
public boolean searchModeIs(int value)
|
||||
{
|
||||
return (mode==value);
|
||||
|
||||
} // end searchModeIs
|
||||
|
||||
public String getSearchTerm()
|
||||
{
|
||||
return term;
|
||||
|
||||
} // end getSearchTerm
|
||||
|
||||
public int getFindCount()
|
||||
{
|
||||
return find_count;
|
||||
|
||||
} // end getFindCount
|
||||
|
||||
public int getOffset()
|
||||
{
|
||||
return offset;
|
||||
|
||||
} // end getOffset
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return display_list.size();
|
||||
|
||||
} // end getSize
|
||||
|
||||
public int getNumResultsDisplayed()
|
||||
{
|
||||
return engine.getStdNumSearchResults();
|
||||
|
||||
} // end getNumResultsDisplayed
|
||||
|
||||
public UserFound getItem(int ndx)
|
||||
{
|
||||
return (UserFound)(display_list.get(ndx));
|
||||
|
||||
} // end getItem
|
||||
|
||||
public void outputDropDown(Writer out, int uid, int cur_level) throws IOException
|
||||
{
|
||||
out.write("<INPUT TYPE=HIDDEN NAME=\"zxcur_" + uid + "\" VALUE=\"" + cur_level + "\">\n");
|
||||
out.write("<SELECT NAME=\"zxnew_" + uid + "\" SIZE=1>\n");
|
||||
if (cur_level==role_sig_host.getLevel()) // cheat and put in just the host level
|
||||
out.write("<OPTION VALUE=\"" + role_sig_host.getLevel() + "\" SELECTED>"
|
||||
+ StringUtil.encodeHTML(role_sig_host.getName()) + "</OPTION>\n");
|
||||
else
|
||||
{ // display all the level choices properly
|
||||
Iterator it = role_choices.iterator();
|
||||
while (it.hasNext())
|
||||
{ // output the <OPTION> lines for the dropdown
|
||||
Role r = (Role)(it.next());
|
||||
out.write("<OPTION VALUE=\"" + r.getLevel() + "\"");
|
||||
if (r.getLevel()==cur_level)
|
||||
out.write(" SELECTED");
|
||||
out.write(">" + StringUtil.encodeHTML(r.getName()) + "</OPTION>\n");
|
||||
|
||||
} // end while
|
||||
|
||||
} // end else
|
||||
|
||||
out.write("</SELECT>\n");
|
||||
|
||||
} // end outputDropDown
|
||||
|
||||
} // end class SIGMembership
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
* (the "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Venice Web Communities System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.venice.servlets.format;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.Writer;
|
||||
import java.io.IOException;
|
||||
|
||||
public class SystemAdminTop extends ContentMenuPanel
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructors
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public SystemAdminTop()
|
||||
{
|
||||
super("System Administration",null);
|
||||
addChoice("Set Global Parameters","TODO");
|
||||
addChoice("View/Edit Banned Users","TODO");
|
||||
addChoice("User Account Management","TODO");
|
||||
|
||||
} // end constructor
|
||||
|
||||
protected SystemAdminTop(SystemAdminTop other)
|
||||
{
|
||||
super(other);
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
return new SystemAdminTop(this);
|
||||
|
||||
} // end clone
|
||||
|
||||
} // end class SystemAdminTop
|
|
@ -325,6 +325,9 @@
|
|||
<INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_go_next.gif") %>" ALT="Post & Go Next"
|
||||
NAME="postnext" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
<% } // end if %>
|
||||
|
||||
<INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_go_topics.gif") %>" ALT="Post & Go Topics"
|
||||
NAME="posttopics" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
</FORM>
|
||||
|
|
|
@ -73,6 +73,9 @@
|
|||
NAME="postnext" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
<% } // end if %>
|
||||
|
||||
<INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_go_topics.gif") %>" ALT="Post & Go Topics"
|
||||
NAME="posttopics" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
|
||||
<INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_cancel.gif") %>" ALT="Cancel"
|
||||
NAME="cancel" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
</TD></TR>
|
||||
|
|
151
web/format/sig_member.jsp
Normal file
151
web/format/sig_member.jsp
Normal file
|
@ -0,0 +1,151 @@
|
|||
<%--
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(the "License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
||||
WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
||||
language governing rights and limitations under the License.
|
||||
|
||||
The Original Code is the Venice Web Communities System.
|
||||
|
||||
The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
--%>
|
||||
<%@ page import = "java.util.*" %>
|
||||
<%@ page import = "com.silverwrist.util.StringUtil" %>
|
||||
<%@ page import = "com.silverwrist.venice.core.*" %>
|
||||
<%@ page import = "com.silverwrist.venice.servlets.Variables" %>
|
||||
<%@ page import = "com.silverwrist.venice.servlets.format.*" %>
|
||||
<%
|
||||
SIGMembership data = SIGMembership.retrieve(request);
|
||||
Variables.failIfNull(data);
|
||||
RenderData rdat = RenderConfig.createRenderData(application,request,response);
|
||||
%>
|
||||
<% rdat.writeContentHeader(out,"Set SIG Membership:",data.getSIGName()); %>
|
||||
<%= rdat.getStdFontTag(null,2) %>
|
||||
<A HREF="<%= rdat.getEncodedServletPath("sigadmin?sig=" + data.getSIGID()) %>">Return to SIG
|
||||
Administration Menu</A>
|
||||
</FONT><P>
|
||||
|
||||
<%= rdat.getStdFontTag(null,3) %><B>Find Users:</B></FONT><P>
|
||||
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("sigadmin") %>">
|
||||
<INPUT TYPE="HIDDEN" NAME="sig" VALUE="<%= data.getSIGID() %>">
|
||||
<INPUT TYPE="HIDDEN" NAME="cmd" VALUE="M">
|
||||
<INPUT TYPE="HIDDEN" NAME="ofs" VALUE="0">
|
||||
<%= rdat.getStdFontTag(null,2) %>
|
||||
Display all users whose
|
||||
<SELECT NAME="field" SIZE=1>
|
||||
<OPTION VALUE="<%= SearchMode.FIELD_USER_NAME %>"
|
||||
<% if (data.searchFieldIs(SearchMode.FIELD_USER_NAME)) { %>SELECTED<% } %> >user name</OPTION>
|
||||
<OPTION VALUE="<%= SearchMode.FIELD_USER_DESCRIPTION %>"
|
||||
<% if (data.searchFieldIs(SearchMode.FIELD_USER_DESCRIPTION)) { %>SELECTED<% } %> >description</OPTION>
|
||||
<OPTION VALUE="<%= SearchMode.FIELD_USER_GIVEN_NAME %>"
|
||||
<% if (data.searchFieldIs(SearchMode.FIELD_USER_GIVEN_NAME)) { %>SELECTED<% } %> >first name</OPTION>
|
||||
<OPTION VALUE="<%= SearchMode.FIELD_USER_FAMILY_NAME %>"
|
||||
<% if (data.searchFieldIs(SearchMode.FIELD_USER_FAMILY_NAME)) { %>SELECTED<% } %> >last name</OPTION>
|
||||
</SELECT><BR>
|
||||
|
||||
<SELECT NAME="mode" SIZE=1>
|
||||
<OPTION VALUE="<%= SearchMode.SEARCH_PREFIX %>"
|
||||
<% if (data.searchModeIs(SearchMode.SEARCH_PREFIX)) { %>SELECTED<% } %> >starts with the string</OPTION>
|
||||
<OPTION VALUE="<%= SearchMode.SEARCH_SUBSTRING %>"
|
||||
<% if (data.searchModeIs(SearchMode.SEARCH_SUBSTRING)) { %>SELECTED<% } %> >contains the string</OPTION>
|
||||
<OPTION VALUE="<%= SearchMode.SEARCH_REGEXP %>"
|
||||
<% if (data.searchModeIs(SearchMode.SEARCH_REGEXP)) { %>SELECTED<% } %> >matches the regular
|
||||
expression</OPTION>
|
||||
</SELECT>
|
||||
<INPUT TYPE=TEXT NAME="term" SIZE=32 MAXLENGTH=255 VALUE="<%= data.getSearchTerm() %>"><BR>
|
||||
<INPUT TYPE=IMAGE NAME="search" SRC="<%= rdat.getFullImagePath("bn_search.gif") %>"
|
||||
ALT="Search" WIDTH=80 HEIGHT=24 BORDER=0><BR>
|
||||
</FONT>
|
||||
</FORM>
|
||||
|
||||
<% if (data.displayList()) { %>
|
||||
<% int dcount = data.getSize(); %>
|
||||
<HR>
|
||||
<% if (data.isSIGMemberList()) { %>
|
||||
<%-- The SIG list header --%>
|
||||
<%= rdat.getStdFontTag(null,3) %><B>
|
||||
Members of SIG "<%= StringUtil.encodeHTML(data.getSIGName()) %>":
|
||||
</B></FONT><BR>
|
||||
<% } else { %>
|
||||
<%
|
||||
// Determine the number of results to display and whether to display a "next" button
|
||||
boolean go_next = false;
|
||||
if (dcount>data.getNumResultsDisplayed())
|
||||
{ // there's a "next"
|
||||
dcount = data.getNumResultsDisplayed();
|
||||
go_next = true;
|
||||
|
||||
} // end if
|
||||
%>
|
||||
<TABLE WIDTH="100%" BORDER=0 ALIGN=CENTER><TR VALIGN=MIDDLE>
|
||||
<TD WIDTH="50%" ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
|
||||
<%-- The search results header --%>
|
||||
<FONT SIZE=+1><B>Search Results:</B></FONT>
|
||||
<% if (data.getFindCount()>0) { %>
|
||||
(Displaying <%= data.getOffset() + 1 %>-<%= data.getOffset() + dcount %> of
|
||||
<%= data.getFindCount() %>)
|
||||
<% } else { %>(None)<% } %>
|
||||
</FONT></TD>
|
||||
<TD WIDTH="50%" ALIGN=RIGHT>
|
||||
<% if (go_next || (data.getOffset()>0)) { %>
|
||||
<%-- The navigational form that allows us to page through the results --%>
|
||||
<% if (rdat.useHTMLComments()) { %><!-- Navigational Form --><% } %>
|
||||
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("sigadmin") %>">
|
||||
<INPUT TYPE=HIDDEN NAME="sig" VALUE="<%= data.getSIGID() %>">
|
||||
<INPUT TYPE=HIDDEN NAME="cmd" VALUE="M">
|
||||
<INPUT TYPE=HIDDEN NAME="ofs" VALUE="<%= data.getOffset() %>">
|
||||
<INPUT TYPE=HIDDEN NAME="field" VALUE="<%= data.getSearchField() %>">
|
||||
<INPUT TYPE=HIDDEN NAME="mode" VALUE="<%= data.getSearchMode() %>">
|
||||
<INPUT TYPE=HIDDEN NAME="term" VALUE="<%= data.getSearchTerm() %>">
|
||||
<INPUT TYPE=HIDDEN NAME="fcount" VALUE="<%= data.getFindCount() %>">
|
||||
<% if (data.getOffset()>0) { %>
|
||||
<INPUT TYPE=IMAGE NAME="previous" SRC="<%= rdat.getFullImagePath("bn_ar_previous.gif") %>"
|
||||
ALT="Previous" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
<% } else { %>
|
||||
<IMG SRC="<%= rdat.getFullImagePath("bn_transparent.gif") %>" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
<% } // end if %>
|
||||
|
||||
<% if (go_next) { %>
|
||||
<INPUT TYPE=IMAGE NAME="next" SRC="<%= rdat.getFullImagePath("bn_ar_next.gif") %>"
|
||||
ALT="Next" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
<% } else { %>
|
||||
<IMG SRC="<%= rdat.getFullImagePath("bn_transparent.gif") %>" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
<% } // end if %>
|
||||
|
||||
</FORM>
|
||||
<% } else { %> <% } %>
|
||||
</TD>
|
||||
</TR></TABLE><BR>
|
||||
<% } // end if %>
|
||||
|
||||
<%-- Display the results of the search --%>
|
||||
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("sigadmin") %>">
|
||||
<INPUT TYPE=HIDDEN NAME="sig" VALUE="<%= data.getSIGID() %>">
|
||||
<INPUT TYPE=HIDDEN NAME="cmd" VALUE="M">
|
||||
<TABLE BORDER=0 ALIGN=LEFT CELLPADDING=0 CELLSPACING=4>
|
||||
<% for (int i=0; i<dcount; i++) { %>
|
||||
<% UserFound uf = data.getItem(i); %>
|
||||
<TR VALIGN=MIDDLE>
|
||||
<TD ALIGN=CENTER WIDTH=14>
|
||||
<IMG SRC="<%= rdat.getFullImagePath("purple-ball.gif") %>" ALT="*" WIDTH=14 HEIGHT=14 BORDER=0>
|
||||
</TD>
|
||||
<TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
|
||||
<A HREF="<%= rdat.getEncodedServletPath("user/" + uf.getName()) %>"><%= uf.getName() %></A>
|
||||
</FONT></TD>
|
||||
<TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
|
||||
<% data.outputDropDown(out,uf.getUID(),uf.getLevel()); %>
|
||||
</FONT></TD>
|
||||
</TR>
|
||||
<% } // end for %>
|
||||
</TABLE><BR CLEAR=LEFT>
|
||||
<INPUT TYPE=IMAGE SRC="<%= rdat.getFullImagePath("bn_update.gif") %>" NAME="update" ALT="Update"
|
||||
WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
</FORM><BR>
|
||||
<% } // end if %>
|
||||
<% rdat.writeFooter(out); %>
|
|
@ -97,6 +97,9 @@
|
|||
NAME="postnext" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
<% } // end if %>
|
||||
|
||||
<INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_go_topics.gif") %>" ALT="Post & Go Topics"
|
||||
NAME="posttopics" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
|
||||
<INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_cancel.gif") %>" ALT="Cancel"
|
||||
NAME="cancel" WIDTH=80 HEIGHT=24 BORDER=0>
|
||||
</TD></TR>
|
||||
|
|
BIN
web/images/bn_post_go_topics.gif
Normal file
BIN
web/images/bn_post_go_topics.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
Loading…
Reference in New Issue
Block a user