⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 securitymanager.java

📁 Rapla是一个灵活的多用户资源管理系统。它提供的一些功能有:日历GUI
💻 JAVA
字号:
/*--------------------------------------------------------------------------*
 | Copyright (C) 2006 Praktikum Gruppe2?, Christopher Kohlhaas              |
 |                                                                          |
 | 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. A copy of the license has been included with   |
 | these distribution in the COPYING file, if not go to www.fsf.org         |
 |                                                                          |
 | As a special exception, you are granted the permissions to link this     |
 | program with every library, which license fulfills the Open Source       |
 | Definition as published by the Open Source Initiative (OSI).             |
 *--------------------------------------------------------------------------*/
package org.rapla.server.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.rapla.components.xmlbundle.I18nBundle;
import org.rapla.entities.Category;
import org.rapla.entities.Ownable;
import org.rapla.entities.User;
import org.rapla.entities.domain.Allocatable;
import org.rapla.entities.domain.Appointment;
import org.rapla.entities.domain.AppointmentFormater;
import org.rapla.entities.domain.Permission;
import org.rapla.entities.domain.Reservation;
import org.rapla.entities.storage.RefEntity;
import org.rapla.facade.Conflict;
import org.rapla.facade.internal.ConflictFinder;
import org.rapla.framework.RaplaContext;
import org.rapla.framework.RaplaContextException;
import org.rapla.framework.RaplaException;
import org.rapla.storage.CachableStorageOperator;
import org.rapla.storage.RaplaSecurityException;

/** checks if the client can store or delete an entity */
public class SecurityManager extends AbstractLogEnabled
{
    protected ConflictFinder conflictFinder;
    I18nBundle i18n;
    AppointmentFormater appointmentFormater;
    CachableStorageOperator operator;

    public SecurityManager(RaplaContext serviceManager) throws RaplaContextException {
        enableLogging( (Logger) serviceManager.lookup( Logger.class.getName()));
        operator = (CachableStorageOperator)serviceManager.lookup( CachableStorageOperator.ROLE);
        conflictFinder = new ConflictFinder( operator );
        i18n = (I18nBundle) serviceManager.lookup(I18nBundle.ROLE + "/org.rapla.RaplaResources");
        appointmentFormater = (AppointmentFormater) serviceManager.lookup(AppointmentFormater.ROLE);
    }

    void checkWritePermissions(User user,RefEntity entity) throws RaplaSecurityException {
        if (user.isAdmin())
            return;

        Object id = entity.getId();
        if (id == null)
            throw new RaplaSecurityException("No id set");

        boolean permitted = false;
        RefEntity original = operator.getCache().get(entity.getId());
        // flag indicates if a user only exchanges allocatables  (needs to have admin-access on the allocatable)
        boolean canExchange = false;

        if (entity instanceof Ownable) {
            User entityOwner = ((Ownable) entity).getOwner();
            if (original == null) {
                permitted = entityOwner != null && user.isIdentical(entityOwner);
                if (getLogger().isDebugEnabled())
                    getLogger().debug("Permissions for new object " + entity
                                    + "\nUser check: " + user  + " = " + entityOwner);
            } else {
                User originalOwner = ((Ownable) original).getOwner();
                if (getLogger().isDebugEnabled())
                    getLogger().debug("Permissions for existing object " + entity
                            + "\nUser check: " + user  + " = " + entityOwner + " = " + originalOwner);
                permitted = (originalOwner != null) && originalOwner.isIdentical(user) && originalOwner.isIdentical(entityOwner);
                if ( !permitted ) {
                	canExchange = canExchange( user, entity, original );
                	permitted = canExchange;
                }
            }
        } else if ( entity instanceof Allocatable ){
            if ( original == null ) {
                permitted = isRegisterer(user);
            } else {
                permitted =  ((Allocatable)original).canModify( user );
            }
        }

        if (!permitted)
            throw new RaplaSecurityException("User '" + user + "' is not allowed to modify object. '" + entity + "'") ;

        // Check if the user can change the reservation
        if ( Reservation.TYPE.equals( entity.getRaplaType()) )
        {
            Reservation reservation = (Reservation) entity ;
            Reservation originalReservation = (Reservation)original;
            Allocatable[] all = reservation.getAllocatables();
            if ( originalReservation != null && canExchange ) {
                List newAllocatabes = new ArrayList( Arrays.asList(reservation.getAllocatables() ) );
                newAllocatabes.removeAll( Arrays.asList( originalReservation.getAllocatables()));
                all = (Allocatable[])newAllocatabes.toArray( Allocatable.ALLOCATABLE_ARRAY);
            }
            checkPermissions( user, reservation, originalReservation , all);
        }
    }

    protected boolean isRegisterer(User user) throws RaplaSecurityException {
        try {
            Category registererGroup = getUserGroupsCategory().getCategory(Permission.GROUP_REGISTERER_KEY);
            return user.belongsTo(registererGroup);
        } catch (RaplaException ex) {
            throw new RaplaSecurityException(ex );
        }
    }

    public Category getUserGroupsCategory() throws RaplaException {
        Category userGroups = operator.getSuperCategory().getCategory(Permission.GROUP_CATEGORY_KEY);
        if ( userGroups == null) {
            throw new RaplaException("No category '" + Permission.GROUP_CATEGORY_KEY + "' available");
        }
        return userGroups;
    }


    /** checks if the user just exchanges one allocatable or removes one. The user needs admin-access on the
     * removed allocatable and the newly inserted allocatable */
    private boolean canExchange(User user, RefEntity entity, RefEntity original) {
        if ( Appointment.TYPE.equals( entity.getRaplaType() )) {
            return ((Appointment) entity).matches( (Appointment) original );
        } if ( Reservation.TYPE.equals( entity.getRaplaType() )) {
            Reservation newReservation = (Reservation) entity;
            Reservation oldReservation = (Reservation) original;
            // We only need to check the length because we compare the appointments above.
            if ( newReservation.getAppointments().length != oldReservation.getAppointments().length )
            {
                return false;
            }

            List oldAllocatables = Arrays.asList(oldReservation.getAllocatables());
            List newAllocatables = Arrays.asList(newReservation.getAllocatables());
            List inserted = new ArrayList(newAllocatables);
            List removed = new ArrayList(oldAllocatables);
            List overlap = new ArrayList(oldAllocatables);
            inserted.removeAll( oldAllocatables );
            removed.removeAll( newAllocatables );
            overlap.retainAll( inserted );
            if ( inserted.size() == 0 && removed.size() == 0)
            {
            	return false;
            }
            //  he must have admin rights on all inserted resources
            Iterator it = inserted.iterator();
            while (it.hasNext()) {
                if (!canAllocateForOthers((Allocatable)it.next(),user))
                {
                    return false;
                }
            }

            //   and  he must have admin rights on all the removed resources
            it = removed.iterator();
            while (it.hasNext()) {
                if (!canAllocateForOthers((Allocatable)it.next(),user))
                {
                    return false;
                }
            }

            // He can't change appointments, only exchange allocatables he has admin-priviliges  for
            it = overlap.iterator();
            while (it.hasNext()) {
                Allocatable all = (Allocatable)it.next();
                Appointment[] r1 = newReservation.getRestriction( all );
                Appointment[] r2 = oldReservation.getRestriction( all );
                boolean changed = false;
                if ( r1.length != r2.length ) {
                    changed = true;
                } else {
                    for ( int i=0; i< r1.length; i++ ) {
                        if ( !r1[i].matches(r2[i]) ) {
                            changed = true;
                        }
                    }
                }
                if ( changed && !canAllocateForOthers( all, user )) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    /** for Thierry, we can make this configurable in the next version */
    private boolean canAllocateForOthers(Allocatable allocatable, User user) {
        // only admins, current behaviour
        return allocatable.canModify( user);
        // everyone who can allocate the resource anytime
        //return allocatable.canAllocate( user, null, null, operator.today());
        // everyone
        //return true;
    }

    private void checkConflictsAllowed(User user, Allocatable allocatable, Conflict[] conflictsBefore, Conflict[] conflictsAfter) throws RaplaSecurityException {
        int nConflictsBefore = 0;
        int nConflictsAfter = 0;
        if ( allocatable.canCreateConflicts( user ) ) {
            return;
        }
        if ( conflictsBefore != null ) {
            for ( int i = 0; i < conflictsBefore.length; i++ ) {
                if ( conflictsBefore[i].getAllocatable().equals ( allocatable ) ) {
                    nConflictsBefore ++;
                }
            }
        }

        for ( int i = 0; i < conflictsAfter.length; i++ ) {
            if ( conflictsAfter[i].getAllocatable().equals ( allocatable ) ) {
                nConflictsAfter ++;
            }
        }
        if ( nConflictsAfter > nConflictsBefore ) {
            String all = allocatable.getName( i18n.getLocale() );
            throw new RaplaSecurityException( i18n.format("warning.no_conflict_permission", all ) );
        }
    }

    private void checkPermissions( User user, Reservation r, Reservation original, Allocatable[] allocatables ) throws RaplaSecurityException {
        Conflict[] conflictsBefore = null;
        Conflict[] conflictsAfter = null;
        try {
            conflictsAfter = conflictFinder.getConflicts( null, r );
            if ( original != null ) {
                conflictsBefore = conflictFinder.getConflicts( null, original );
            }
        } catch ( RaplaException ex ) {
            throw new RaplaSecurityException(" Can't check permissions due to:" + ex.getMessage(), ex );
        }

        Appointment[] appointments = r.getAppointments();
        // ceck if the user has the permisson to add allocations in the given time
        for (int i = 0; i < allocatables.length; i++ ) {
            Allocatable allocatable = allocatables[i];
            checkConflictsAllowed( user, allocatable, conflictsBefore, conflictsAfter );
            for (int j = 0; j < appointments.length; j++ ) {
                Appointment appointment = appointments[j];
                if ( r.hasAllocated( allocatable, appointment ) &&
                     !conflictFinder.hasPermissionToAllocate( user, appointment, allocatable, original ) ) {
                    String all = allocatable.getName( i18n.getLocale() );
                    String app = appointmentFormater.getSummary( appointment );
                    String error = i18n.format("warning.no_reserve_permission"
                                               ,all
                                               ,app);
                    throw new RaplaSecurityException( error );
                }
            }
        }
        if (original == null )
            return;

        Date today = operator.today();

        // 1. calculate the deleted assignments from allocatable to appointments
        // 2. check if they were allowed to change in the specified time
        appointments = original.getAppointments();
        allocatables = original.getAllocatables();
        for (int i = 0; i < allocatables.length; i++ ) {
            Allocatable allocatable = allocatables[i];
            for (int j = 0; j < appointments.length; j++ ) {
                Appointment appointment = appointments[j];
                if ( original.hasAllocated( allocatable, appointment )
                     && !r.hasAllocated( allocatable, appointment ) ) {
                    Date start = appointment.getStart();
                    Date end = appointment.getMaxEnd();
                    if ( !allocatable.canAllocate( user, start, end, today ) ) {
                        String all = allocatable.getName( i18n.getLocale() );
                        String app = appointmentFormater.getSummary( appointment );
                        String error = i18n.format("warning.no_reserve_permission"
                                                   ,all
                                                   ,app);
                        throw new RaplaSecurityException( error );
                    }
                }
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -