Måste ge ett värde till alla properties som är deklarerade med not-null genom:
Anledningen är att vi vill få en InvalidDataException
direkt och inte
något databasfel vid DbControl.commit()
. T.ex. ska nedanstående kod
fungera:
Item i = Item.getNew(dc); dc.saveItem(i); dc.commit(); // Se även punkt 2. test_create()
ReporterType.getNew: public static ReporterType getNew(DbControl dc) throws PermissionDeniedException, BaseException { return dc.newItem(ReporterType.class); } // Saknar setName()
Directory.getNew: public static Directory getNew(DbControl dc) throws BaseException { Directory d = dc.newItem(Directory.class); d.setParent(Directory.getById(dc, SystemItems.getId(Directory.ROOT))); return d; } // Saknar setName() // Använd DirectoryData istället för Directory, eller... // Skicka med ett Directory som parameter (se t.ex. File.getNew nedan)
File.getNew: public static File getNew(DbControl dc, Directory directory) throws BaseException { File file = dc.newItem(File.class); file.setAction(File.Action.NOTHING); file.setLocation(Location.OFFLINE); file.setDirectory(directory); return file; } // Saknar setName()
Lämpligt värde för name är "New reporter type", "New file", etc.
För att testa att getNew() fungerar enligt ovan bör test_create() konstrueras så att man kan testa både med och utan att man sätter några värden på en ny item. T.ex:
TestRole.test_create: static int test_create(boolean setAll) { if (!TestUtil.hasPermission(Permission.CREATE, Item.ROLE)) return 0; int id = 0; DbControl dc = null; try { dc = TestUtil.getDbControl(); Role r = Role.getNew(dc); if (setAll) { r.setName("Test role"); r.setDescription("Added at "+new Date()); } dc.saveItem(r); dc.commit(); id = r.getId(); write_item(0, r); write("--Create role OK"); } catch (Throwable ex) { write("--Create role FAILED"); ex.printStackTrace(); ok = false; } finally { if (dc != null) dc.close(); } return id; } // Notera parameters setAll (markerat med fet-stil)
User.setLogin: public void setLogin(String login) throws PermissionDeniedException, InvalidDataException { checkPermission(Permission.WRITE); getData().setLogin(StringUtil.setNotNullString(login, "login", MAX_LOGIN_LENGTH)); } // Inga fel
File.setMimeType: public void setMimeType(String mimeType) throws PermissionDeniedException { checkPermission(Permission.WRITE); getData().setMimeType(mimeType); } // Validerar ej max-läng på mimeType (null är tillåtet) // Använd t.ex. StringUtil.setNullableString(...)
File.setLocation: public void setLocation(Location location) throws PermissionDeniedException { checkPermission(Permission.WRITE); getData().setLocation(location.getValue()); } // Validerar ej att location != null
File.setFileType: public void setFileType(FileType filetype) throws PermissionDeniedException { checkPermission(Permission.WRITE); getData().setFileType(filetype.getData()); } // null är tillåtet men det måste kollas innan filetype.getData(). Använd ?-operatorn.
För validering av stränglängd deklareras public static final int MAX_XXX_LENGTH
i Data-klasserna och i Item-klasserna:
UserData: public static final int MAX_LOGIN_LENGTH = 255; User: public static final int MAX_LOGIN_LENGTH = UserData.MAX_LOGIN_LENGTH;
File.setDirectory: public void setDirectory(Directory directory) throws PermissionDeniedException { checkPermission(Permission.WRITE); getData().setDirectory(directory.getData()); } // Validerar ej att directory != null // Kontrollerar ej USE-permission på directory
Software.setSoftwareType: public void setSoftwareType(SoftwareType hardwaretype) throws PermissionDeniedException, InvalidUseOfNullException { if (hardwaretype == null) throw new InvalidUseOfNullException("hardwaretype"); hardwaretype.checkPermission(Permission.USE); getData().setSoftwareType(hardwaretype.getData()); } // Saknar checkPermission(Permission.WRITE)
Directory.setParent: public void setParent(Directory parent) throws PermissionDeniedException, InvalidUseOfNullException { if (parent != null) { parent.checkPermission(Permission.WRITE); getData().setParent(parent.getData()); } else { throw new InvalidUseOfNullException("A directory must have a parent directory"); } } // "Felaktig" ordning på kontrollerna
Directory.getParent: public Directory getParent() throws PermissionDeniedException, BaseException { Directory parent = null; if(getData().getParent() != null) { parent = getDbControl().getItem(Directory.class, getData().getParent()); parent.checkPermission(Permission.READ); } return parent; } // Onödig kontroll av != null // Onödig kontroll av Permission.READ
Om klassen ärver ifrån OwnedItem
, SharedItem
eller CommonItem
behöver man normalt inte göra något speciellt med dessa metoder. initPermissions()
behövs inte alls, och getQuery()
blir enkel:
Client.getQuery: public static QuerygetQuery(DbControl dbControl) throws BaseException { return new ItemQuery (dbControl, Client.class); }
Om man ärver ifrån BasicItem
kan det bli mycket mer komplierat. Man
måste själv se till att getQuery()
inte returnerar objekt som man
inte har READ-permission till. Detta måste synkas med initPermissions()
.
Group.getQuery: public static QuerygetQuery(DbControl dc) throws BaseException { Query query = new ItemQuery (dc, Group.class); SessionControl sc = dc.getSessionControl(); if (!sc.hasPermission(Permission.READ, Item.GROUP)) { Expression id = Expressions.property(query.rootAlias()+".id"); if (sc.isLoggedIn()) { // Load groups where the logged in user is a member query.addPermanent(Restrictions.in(id, Expressions.parameter("groups"))); query.setPermanentParameter("groups", sc.getGroups()); } else { // Do not load any groups if not logged in query.addPermanent(Restrictions.neq(id, id)); } } return query; } Group.initPermissions: void initPermissions(int granted, int denied) throws BaseException { if (isSystemItem()) { denied |= Permission.deny(Permission.DELETE, Permission.CREATE); } if (getSessionControl().isMemberOf(this)) { granted |= Permission.grant(Permission.READ); } super.initPermissions(granted, denied); }
Notera att BasicItem.initPermissions()
ger permissions enligt de roller
man är tilldelad så även om man inte behöver ändra på detta så måste man ta hänsyn till
den kontrollen i getQuery()
.
Abc.getQuery: public static QuerygetQuery(DbControl dc) throws BaseException { Query query = new ItemQuery (dc, Abc.class); SessionControl sc = dc.getSessionControl(); if (!sc.hasPermission(Permission.READ, Item.ABC)) { Expression id = Expressions.property(query.rootAlias()+".id"); // Do not load any abc if READ permission is missing query.addPermanent(Restrictions.neq(id, id)); } return query; }
Om man har en klass med parent/child relation så är det lämpligt att
getQuery()
får en extra parameter:
Help.getQuery: public static QuerygetQuery(DbControl dc, Client client) throws BaseException { Query query = new ItemQuery (dc, Help.class); if (client == null) { if (!dc.getSessionControl().hasPermission(Permission.READ, Item.CLIENT)) { // Do not return any help Expression id = Expressions.property(query.rootAlias()+".id"); query.addPermanent(Restrictions.neq(id, id)); } } else { // Return help for the specified client query.addPermanent( Restrictions.eq( Expressions.property(query.rootAlias()+".client"), Expressions.integer(client.getId()) ) ); } return query; } Help.initPermissions: void initPermissions(int granted, int denied) throws BaseException { Client c = getClient(); if (c.hasPermission(Permission.READ)) { granted |= Permission.grant(Permission.READ); } if (c.hasPermission(Permission.WRITE)) { granted |= Permission.grant(Permission.WRITE, Permission.DELETE, Permission.CREATE); } super.initPermissions(granted, denied); }