From 06d67ed4af9d1493a98c2751591ce632c628dcc7 Mon Sep 17 00:00:00 2001
From: Adrian Damian <Adrian.Damian@nrc.ca>
Date: Fri, 27 Jun 2014 11:47:26 -0700
Subject: [PATCH] Added the core authorization classes - code review changes

---
 projects/cadcUtil/doc/uml/UserAuth.png        | Bin 16427 -> 17155 bytes
 .../src/ca/nrc/cadc/auth/model/Group.java     |   9 +-
 .../ca/nrc/cadc/auth/model/GroupProperty.java |  24 +--
 .../ca/nrc/cadc/auth/model/PosixDetails.java  |   2 +-
 .../src/ca/nrc/cadc/auth/model/User.java      |   6 +-
 .../ca/nrc/cadc/auth/model/UserDetails.java   | 158 +-----------------
 .../src/ca/nrc/cadc/auth/model/GroupTest.java |  36 +++-
 .../src/ca/nrc/cadc/auth/model/UserTest.java  |  27 +--
 8 files changed, 67 insertions(+), 195 deletions(-)

diff --git a/projects/cadcUtil/doc/uml/UserAuth.png b/projects/cadcUtil/doc/uml/UserAuth.png
index c36dfcc1fe9c2513edec0e715a4318b130ea89a2..64354ac504dff79d1f26a7e0e17100cb82bac64a 100644
GIT binary patch
literal 17155
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
E0o1xNmH+?%

literal 16427
zcmc(G2UyeB`)?S6Q9v*bRJJu*WkpI^LRg9;MI2QWWL9Va0YO1_fGD^?tc8FqwG^!^
zMW#RiQLv1FBA|q&LXZGKrb$S+?+M!5U+-_+`~05&bDKUIzu$A-^Pczpyz`t~w6V65
zUbcQ227{5_v)l3@1|yEcU_{%NO28BBx2!G<hB&#$((LfLH)B1gtlyWuAv;qj?Qhra
z)8{!pA01M^<v5~9bsPDrSUKXW0KZ?({B+^B$luQlKGC~4HQBcym|FsLGH;xRKQXab
z_=8OSXJ0WcqVQM+kKX<Bum5K9BFX=;$wGeqIot5mH$l3;vC-$vIb{*F!II0^#OOgu
zv`r^%FOCS>lf0B&xN!FpPZE{U{>U{2Uxr-y^5w5%N#*(EmR^&}<Fq<)Otf?33i5LH
zw(teP^72oYu<ZCuC;mztM(TnF5mP6=<qB3=Ib(r;5<RotFuGpqG8PyKRJ@VTtst5R
zHsWKk<Va?h**z+-qJkey-MXM<CG#R=e!e4L4kwEv58|D+^8E>BB#bFZf23s6%7m^&
zq|I<HVPmnT0TY6kQ!2hJdWk^LTTPfLvU7A?kK0>Cr_+BC^mNdD_?$FJ28ihBRcx7#
z<gCdY|MZCasK(DPnAd{6%jmz%s}n>BA{0trmU2?~cY8<;VPVfRcBWg6yc_o09ab@8
ze@JYE(RmT^?Ej2XSrg)+;=o&|Ot<*J+A6)=Mbt%9pC1}{t%v8im*~iK&mwMKi}T3v
ze?NNZdZ9&XG6=fhSt>TcEGWJv<U`-R<f+U-PAqV)f+wxU`MGcK8tb<Lx*5Nex8M0@
zC1^+=A9QToTB5B{Wv{^DIeq_$KWzNm%r$S6HUXcdp`_S~;$C<Bd(9<ZE80A662atc
zz{Qm|-KzJ`G1yRZQYIGb)Iyn<muxFrc6`WiOByqCW_wIZ*+#V_0|qBfZc!3e^kiA%
zJGX{Hs5(G&sbjvQVZr{M*G{ZQ{NWx2HTMlS!ZWT@ZT$6OlwjINDS3>oF<#-cUJPR{
zo>8Pa!_@RQC1HM3{*<d<a3%G7*{kb&4`H<3NlqtRqNo^!9j!)hONK$>Mee&{M=E#~
zP;&KTlA*lqdW1E!e|Rp08<OB>!~rJJbRjNP@MMGsc_~+p$l`pAp29>&xJ=_x3@FTu
zR3J;fDHD7rB5qKeOhq4{ie`WQhmFaE244r@IWo7pwKE3Mg7>1B77}?<2UjOf5b2+;
z@fml85q09|LynLp&k2+XB0%0B7+xH{_99mFJWK{|vt^<(7A{jU)f|HAoUR5zb+YL8
zd9<$Zt-g*KNfywGd9%X1>X;I&RR5I1$S{rwXU&q0U25kRe8T$L>5axojH%|Zab};K
zEMmeGCShc8Q3Pk7YklulUTk+Vnc1<Co<9SO5hCrR8pvCHG8~=)laxu3uzYIkBuB3A
z&~91SfxV>Us@`p!LB8B7v<b>A=quTxIT;(0wDm?PeYg`@7Kr_s$n*M#MwSE-ve7fj
z@UK@BZ2P;83wb3svSopEa2=)HhY66d32`(3utRDSy)PMwlB_6x$2wYXUA*FL*mYLi
z>Wp}w;GX7Nfh2vFH{cBE?F2j8E2vxb62SI|{Q^}66jQyS;n~MWX)V2Bv3H7$^uE3p
zu>!4*slPNcwOv2mZ}clXS+VX6;nw?<Cn+yEqnI(ogu=Gjvcs<k@vfT*BBLtSm$AAf
zN`@XCF0eJ<oY=*ucoPtEfyFA^=SQ%Xj3}W-<^Ty({Xh*d6d<brn7tmN%+$Pkw`}e9
z`Y~Br5)DA%x|24HWL*%Q=`or9f+uS=9yaPN<3BFDpw6Qy7w%dD@{y~*RF?mffyu?t
z+;=L-D-cACnl}Z+(&Yv?1iQnaDci9oaoD1%@KgFihOkb~?dmd6c2WJMdxffp0*gG1
z{ry<XQRA5Q*SE6VBX`jR90LP~m7p*5S?O=zZrl=wX6V*mN-#*jJ!P;{Goj(cuH!sL
zNca^%8X)h4MeUKp`q5)5I_!-8#_sH+tf%&bTW79+7*6}`Ho>{r$laiLjgX?sH#I}Q
zyKg4*am&5j`;^UUf=|bPfk9T%k2gpG8UO+$7t<M;)31VXnVrdEm0Cp)BHq%g$DUMM
zkmQ5i%vs6HH4Rn+!BG|Rkm6g9z%yhee{ajamwgcn9NO%D`EyjAf!Ia`zbSRg44Muu
z=cSNhiQ-%T!?JRv9=m_UF1t7Lb}uix-Ro0vmW0yykoLFu)U$e$Xrzm1>m!R*atN}7
zn(B8l^_Px@6YY-X!YlAqF-viEl*cEAY}Vt{XkS-0hK-$aXPW2?{9a;l=Dro{5f$TI
zxkOT%An#%h&<;!?KRBb^F}2=XY(?Csr-z=OT;5sg`twq!v^BWuWUN!-X(}GiIJs~b
zhYN1e^y!a0E64f<F{^^Fo(}Zy;+DEuFG(^e&997%aow5oG8WrqMpjg_|Fpf#o)o+5
z{Nw%A!&S4zg}E$e)>n7qRzCnB!qh!RmVtg`?&DN@4g6@@DH|R4s78e?1{Qbg8Jj{_
zx8GTzeOB0q)uz4)S$MPO#Y2nvsa_sWb!&CyW+(MBpRoAH2J+`@BZBu+%FRhzPLzzF
z>264lKaXVKQhPA_dhcL~UTVZOo`PJu@@>%@8CgytS0iJnt?#<nIgM0><#yRm#l6?z
z(%DB(Ol`Q%q`wN!Pv0=jsQaEyFF6^czqG2y%zL|9?6Q|qwvNi`@w&I8#<oZ(P1RG@
z#jU;*xbL;$_%;Kj9-|9aDxM8bK7RY4;OucyzXU-w_>|j+vl(q6?pAs^x*1wQmBx-@
zokpk1W>vQ;l;?)5#&z7ZX$g=Jiw|-&Z+vio?)o%^YO_6N&j-5tF%#YVTW)VVR>ujq
zp=Y3TE8xkh9<%lq?;e)ngOryw#~sAXYaI?_QU}gQ*8iSlaAp4Kq2`}>Z8Z^NSt3@7
zb`FEKU4|L}c*=O-iG$m%luYBgB4e@h><{5B));qq(FDfau5tY6Wo*K`mN!(JDV>&B
z?0w}$aVX(-bq*!q+G4R+3>$QPL{TUkX!>+yJ+8P)vuJ+`-}ZESGFHRAxj6khRUqbj
zliE6ESlV&uaqy|p+Z$~B@%jxtk2QXc#f%SCmr|W>8oKdWr*rf@S|};5kB1c`H|1xa
zZJ|tWx)E_=*47rBhi~$eA*l*oqgaTM!S<Wiq)q=e^Kiv@5a?~S!i3)|&qr2a#O?zJ
zyI(i>bbO#`b|`Gv887Y0mTL1mVmj?DlNDjYUF*J0artF1$+huVdv^Mh)Ie^on0<@k
zrwjvpyWrbZ-LGFfH#)U3b<=x!zm`r_p$iwco~bRW@SToa$bqQC@UjYe({iLouCBOt
zev^5veSK|Q8gecVb$E6Vcv@C<rDHVKiX6n<<ImfFg@0c)H^tn$;QjvWujwHpY>O4e
z2gY+AJ{$WjKSF)9YY(_G%&08(8RdHNt9``Y$Iacn8G|NqEto#mJH{Bx%iYU0IeKm*
zT0$0AEt9av#hlf-%f&oC<YkEo{Y9bPXomdiRbJVt$z<2fh>Ze^_Xm><-b)ZSMNe1K
zl=;261XZpfJnCwh@Hg6~270Quj>W3W<3@J_JruS&%;TxDoZd=0Db~7wc)O%u_c6Je
z9tGb~3dGme8D?UyWY9FlK%;YABI9OBz31<ha}TP2h}rFB<6z`&-Z&_d+ZWQ#kVz=i
zlXBYfy5-W+`W}yt5V?A57g2j|6GbQ8Rnw{6B%7gLs$=4AWZ8`q%$?!)2KwK<h;3t^
zScwa+l1VaXEl*o5_pCSXRk<+Sm>b11NL6KhRh^;ZymuKH-R16M9i7>N9o!9^hGR=M
z(O%`h#wsh~_9nTG^x-Gj;aPSnuT`TA!V1zVT`UVUUBD%&R77`exNBu%&F=_dvxlt9
z;suP9{P^@qqAN-MBWIZQ-I>?js-hCw_RdCjhFZH>S?e?$ar|WOt9v4pk;L;9aJRE-
zlG5?Ye0vssjKjHKM@ccjwb&NR_|*uWJEd&%cE6LPF>?u9<mhwa*M(45h}+e<uIBHz
zFC{qVfy?eY1i&>V_5acRx}%KfR}$2`B)XlUx{0o;r?uyK>ZUf1eZ^Wi@Xhi8Zsv`q
z-@|By_rQ^YBJQ|}=DJ_4d^+DuD%>vdzS`UNbWx;I$vUcfzE_%(TMd~t4f$+2)4lX|
z{ooeLMwci99EK2i%*FgerqN2V;Cjj%W-E(hyY@5${c68J|5$s61YVVHp#QM$G3V#>
z24k87{cEm*r}=l!k8Kzqf}ATy3Ab0%e|L|rDkQxl2V;geDQNmvKft+&mKfXK{8*O$
zF*Wbup|xn4?_F!<k_@J)bq|KT#FGsA0m~S|K*63L95i`TyIL9{lDdcvk?tCOPIM9K
z0Cy(Q?8dB?yaEex-eyL#YVco^TH!)69n~^&qZtKhif59=I(8};UBo&`iUh=Je-Jzq
zU<ox3)H;4b&<c=siuo~S>35yKcN10d`bX*vuR_jb*=e^n<xb7K+|e%8T@uzRTji^r
z`c?5xX}iGEmNtzjr<JnrV&{*CKO1Ix)|<@9e5BJjeJc)#yrroYr=gHsjp$HYcgXf~
zQ`(G5I;h%{oHq~XWfq}vOX)E15BkBbOAi@8Lx4cZZnYX9)#sJJ*kD7aPgvfNyEmV~
zV66}Owq}@V^fu(gSn*X!w(QSxW{0V6)m*MqP>$ScuglsKkPKOG#25TX+8t)U5-O&u
zA$F0VDJ7qMdUoeDXIJ8P^v?07m`{W1MJo;rw4Um@Pc1ldxIpnOJzy4biE<#PU#PNB
zV9ZWsO>KUZu5myo(881Sqw(WAZtIjjzWIP#S$tb`;;s7EDAN^wZuyX6Q-^4J<UU>~
zTV$rK(f7B`@cPXDQE^{4QIx%-w3Aw3N{a1WeS5}$u7q<79t-SIP0<r+N+!dGF&#gl
z^jtiz#;3A3qAnGig)??I4IaBw6F=RpT7E}t`ti-^F)0afgdIQCiEEzGi^)x1pqJjX
z7-#NE_XjVW>yJ+j(vx(@D-?o6m#K+*v7@D&zR1IOpizNbu6R2ZbCz{JOb&u*v#V$r
zRdOftlaggJez*KBL2_wn-j!jzX@NY(M4*xR^yuz$5f%A4jwsvFZ#a8x`FBa*KyJ}u
zT{&JAzT~`P>+^T~X%DD?eH9hZ`$o}hJX?BX&P2fJYyawENJfMpn77%>T?9GMYBSBt
zJ#HTjR^EWbyze{y6{V^3T|{T2<tRBMN89Uju1Dn-;${UKI7$ih?!UZ|EMx4zd&vQN
zOHeIBZZga3-Z0QaF~MoR0f>Tmp}MpBSAV?aW*7A|9bvf$M&cq0;V~ieS~<>QAE|*a
zg>;4Vi&1zV#m5yF!VrC1G08Hg1<IH@R6JlIW}02Z(|5*3dr$5FvhWttb}$)!k?wvg
z4+mK&suXe}shHXQjDXwSejSQnuRpu-Bp{!+)xpQEp3<Vd8GAS*X-ca035U#0B_R5)
zuucT(tHv^*w?L~14c*aEm@ep@;|tss-FgS-KFzINC9Kw9YcKdOSx0R?=~lDZ^_`hh
zYY%DB^vo8SCWz<<(dKxL(3m)xHn@4q=WS!MS6o<fekL)a@J}L#Bx_x2QyTNXRbp(?
zd{klmaY>zc!}wR=3^(8uuGFlLb~bZv9_(~&4S7{MF;&!FrO6VH#ZC~7nzHx&EVb;G
zKdH;E(<{cQC9;6(#5wVyWHQA42WV$dP5mvq3^B5+GmY^#@;r<8Y4<tV+7!&^`E>xs
zW3f{4OK*#wxs3gul`^)fNk?`KPMvnY4oVPNoW44waW=}h;2h6lyZ(}q#J-t#wViz-
zVNiV#A}8X8wiqkj7QM0@YsY%C&MTXsg66so*?p3MoI(Y!J#(S!HP+YO#&%{@T=J5<
z)P|*Y;q_@nzK2QYdaH;Fy!R%>@j&Qiz4#O!yq$KQzE70cPN`Vw3mP=fmXd4SpiRm~
zm!$!Rl(%<P)J!w%Eb`7+NlL~plJa+03FWwUPYrj<)XI`vMNlotdu>u<FXqCE91JWe
zTm$+c-0F^N%#`KUQ<!I)XR$*Yr0gWsiKk(6vbYqPWm3zW50eVQqJkvrIz$@x+ZQ-O
z#VyG~)qu=;)o=6*)zyhp8eMwe+oI1Bz#=5C^z(f<2A(xEEfsv%>q`J(c`5Q7ZLogb
z=^7dV>`eGf-$tAr0rWnN^{tb|je0$Wd__v4n%6h!`YCj|AQ!5|mLm`$YDCn|E!c%q
z=*K76(%{95g)7U{z`%_PYv*r9Q^{$$$P<ZKjAm3WXb@{*6(h8YH4axN)#x)gxDik0
z7Y^2YHF~zw*PmX#7d+udD(2BANRWWao$g7GN>*({#0FldVK8sngQtQo2q2xyX<)~T
zw7t{IvEr7Q8F1YlL1KbQ&NAqj%{0tnD`2UXOW2KqQ^gWw&7ZS6lhd{-6EDKLf}rqx
zN3(&>nsD}fQrGtR=i3dK{35Sodh*qR*M0@_aXjhp=Rd^gI{s{=qv}_Gp`lNA%WoR^
zoDjEc*vr^gjZY~it}+MJmDyU|n<oS%^DRAAC872YE9R>3Yu5xfMXTVcL{^KxHCoL2
zAt|o>8C!->GdU%A7$yob^=UbYySOB)u^5k^4!wF`>US%X&Ro|A8(pgD!VcZ2m-MXq
zea)YhkD2s37Vk&eYF5ViP06)4Ik)mg#R#{?-FHPeu%>W;fKe}>$2<I#ahI`yj^SU1
z=bm#jf6uae8$^G;4%$Zd3YQ*qUl$rNKjp7WoZ{p}2^%NFti}0SkNu09-dNP8C8f<J
zjp2|ox3wh8R!XVq(anEop*)7hOXiNr)9>AfOybf%+DtC!WE7z$P1o!7qu;H^jhD|?
z(B5c@iF8Y;(;o0x?aY0e`_2jclMEg~!XgsNqUS)D4v*J|f}*Bn_C=#AmnlQ4qin0B
zwR|eU33dGBqztEVnFn2^3q(E{=Kr%%Ike|$S~~n>ajCzk;1$A$C{#@ELZWhD9CX2!
zPVdmUHN@*kz1qKBvQFHnd!JVHMm%=Ad(_;~=gAo2{te$Xmn){p-XCQ76KO+JE~02x
z_PY2{eqxnd3*`-Da&#b&n4av^0wKc4u90cp**~XLip8FyozG8}-8QG2OY|?!m*gp{
z6OUZMmhBURUX3buN-glzZhl##0+ReOFV1wuD<}H88-R%HX)Aa7INvxVwXBuLiR7<H
zRKEXAT(DgP(zvv-uq66u_N^qwA3u5iHuz>;+D1YR@26&}><ML$j&;b_YY<VaLab!p
z$~dz=_<1hXV|+szPbtd`M)Ik$ilgxYfz!g3L6oMb;GNt(3yyM(OIo&XseFHHhLiM6
zoSkLzVC(u2kGDtmjczq4tVzW>EqHNIt%mG8eKyro^7poU9BxGGn5`~8bw==e*;kqG
zIVKT#XRRrWx!C#nH=R<mblY$g*N`Rm(ANxe%AZoWbM?QwZ-NPiu6+AbQ3nblo=u{R
z1p;^B*leh$gT*Nlb?lqz7Z)dw(@A$v^!7S_)WOAFAuP%r1xZ9wQhL_SP`WaZG<;f5
zlAT`+Ln?Myk}zNrE0AM?Fj@1{aIfRqkcihN$4t&GxC)s^Kr@s+L7EWw6?ke3L4ZOm
zNHzCmE1!2R;v%+}h>V2LO(Q<ypvFjEX<_qsPPUU=so4q|d?Jt^d6JARIO`S#vhy9N
zaqxIp&8SbnE>XO4E+Qx*XaPCE#RL%C)u1cqm`UOa1RB);1<n8=^^=96>dF&>`bk$J
zeyP-=h!W!m-8r@<{rvdB`mYJj?2vpV?R2e|IYEj?vEQQX>u<zd%m+QoS;rLr$*Y@U
zZ`*y|W)L%YDeMJ0e;0ACdx1&+#e~*T6F$P)=P=d5$`6t*v|Nswf-N1B59ZaC8zqsO
ztE1fRdz5YB$So>zJi1<OwuRClUFRP?okC}7#>9p@fT{`#i$V+joRIjq>DKfk!R}Q*
za*{QiZx8uh9!|wpMmLj^4*hLgKA?hCC;YB)L(e#+86Hv%d~N!^iIR}Cv|VccsSvKf
z1by;BD3b8IVzBw}Qywyr2i);jQg0l9h5ycJnvO)UgNx0iaY%D=YjCnfeq_Wqc+_hE
zW1p<~EaH-R+u7|g*XhjhNgG2m=kamLg!p}0r-upd<{v!c(rX4#zcipYaYbSVs7e^S
z9uXor7Xf7d@HB>M`lEvc!qq<zm&GkT;XrulkJ^aK^ooBC%Fw443XUyQ&%Oj)_nSmo
z0JJfZ{+Qy7L}e7tTtxewWU6Oz2&W)@j6#!$6YnPuK_A}~aLNRs5#DFAW?N@p3Sz1V
z104GC+qJ!OTAZ@`qzkr>EAnJL5xjl1CA(%xh0-|OXasc|e!4ts;CmPI@v^=TS5T)H
zk+q*~q9_HL96PyzKNXbNJM&af&rRfA<#m{H43>KF6T{ghb9Q}!?04-x3nl69TMti{
z7r7vG_&@j42$I$jq63nKezop|_WqBk(hgAyHHpY*r~kOFE^!B)LBCQ*>9BcFRB<F0
zyQ%RHL4CkRzhsN&Kk>`@UL@5~hJ6+`(hc-v>C!JeO)~7f+vt};s^n;c%n;HR{y8nt
z8{sB13t5gwCo7LjJTaD_Yq;y)fU~9H>z6Gy5&O6s@zb$lxk=)d5+5p~c8%Ffv>D($
zG_U>`B#r73===9b<ZU$Ro80g*g(}+<-lBxN{Sm)DqE0+67JKjI)W$wy;MW$cWb8&Q
zxx4E=3D-u`YN*%BSKVfwl*uLBf&&<b#z#zA616&(+PZzIb+fAW2!QhE?dS+gcyb};
zQrjRhd)GiT*qULxe&1~P&8>KC-btAvF_yjhu&%o~>!eJjgrJQobpMc<Ti?{Vb@m$3
zrG@f>9pXlkUwzKw&LwK~Ug*4-n|f4dJm#6bfA?aaLU2>E4L9XZ!m}QT0FY?OufgqQ
zUvCW#GS@V;9A8El*&g#_>Tsn-9OY;G8y~_XV)-jV2$8zT{ecYo4|XTq$*|f(ie+5z
z`{Dh?XV*LQZ(KH<CB|YspNXLs9Y$sdQmWaPJPAVN+Zvv_Dmn%MD3Zrwsr_ND#}<7l
zkivBDR~Lp1A*{$_*`K`^MxQEHz<)F^iyJC45<xPD2c^%yeK_k6#!}A#aLO#H#BUB2
zIArzNwIXi`+b?|{@IqsS1~E0cV5Z2}V##M+!HH7FpcNkfKD=>ZzN}qi`98Y*up-Wn
zxWFl68)r0lKDK-GnSyPA-7&7aZ8(I&T(dxrR%L1NkPP~g$i%|+dmWe^Qx`)WNChSr
zk$TX9)G>#WIBdc`iQ7}SE3sHze|)?BdO1!7gf@f`oR5~jvMc96pqu&lB)Oq}Q{VkL
z(+anKEn)W^q{R5)X4%|=ZTK{#3+q<|I}R;In9sx?w5DP;k_<-EvV5VWwW<^M|1wX#
zyeCwkm8g7*plY~a`hI(i4wKYyBJTiBh0!dOG(n`=scW*(zD~US#Bmflp;oJ|>u&K$
zi~#}ry6y0Fi<*JP2%Mv!gIZ9M$c&-|3Mw$LM$Fp*O08f=Cw_GRRJglQBgmAb5>hbu
z@oejYK!0Mcs+v3C{8$YLBd-Esyx{P;)`fvg5mrph*rmk-yI5?~cH5LNo1sh*f^*A^
z-we~|@xyR9NmXt$M^$8<cy!joLje(_XYD>Vt)8tmyfB4te6y$pVG*DD4&_IKKdOCz
z+iF5&zvw)jbk2pp8r3@1(OJ2)wbF7r3;362V$cIVDo;h`<?20C8pyM9|7wvT-`%8G
zDF;8=*F9YQ8M{}x^rCcwfy~Iqbrkl(LRsFgCXVGYyE=J{;B9zqHT<vPMsRYR+t<$y
z6Yv&F1QpZnaplIYBdm@2n`byFgI^0J7)7;Ng*&KhCGZ~cRGi+3uj{DqpqJz{Zfdh2
zWgaDM;f#gS<M+{ioA!#dmmLnfuyfomc9@C6iz!Ll-Mr05)>BeiLk!i?s^R$7yJriA
z{FW0U?`Ziqq>c1VO|>;HR}*7jr)@~n8Mr&RsI}T=iG8`z@eCiGISC6Skxx1o<Djp{
zDyN#}H!6U)N!Yh}*NLIl^#@Vf1trHts*RD&N=T_YE@CzPot`x+v?%SEGdzTFu{hwd
z!6?7@L47K=sMFJE*oq{-7PqS@xxYy~E)HAC+<iAKus_ED2c(C-sA)oRO<dJYixE27
z_Vi_J+1Y|Km0GX8p~+s+q`F%E`1nw(pX5czN5QeQ@*b`TL<hl0!7n9=GF&-a-df%9
z3GS(*LmA|Rcak4asIfm+(5HiWU)AZKyG9+#Ile9U0T9hV@JFcpW3l~Bk>iA0vt^+R
zeCEQ#4ySuV4`C2!SJ(@(wz2(MsA|#!+&+E>pNaVtWSYiJVfajLB>F>FHQal|9rdFN
z)sE9WCQNi~{aWK^o;(3OV<1M6KR`3GUf1y@_w;je)%%d&sxqif1@AMJh4=-_Kz$Cf
zwZGgAnO`?L>NL`KY{i#0)i^yjqs_4!436d~D-~~pT_7VOch^xG2A3OGF<&Pc#4dG-
ziVp97eZW7@mbk;~C{haRXDX(|Sm&18MDIHczX6;>e`epe0d*%2cC1*@{fp;QibJI8
zT%~7t%Yl#YI7t?|^Z}V$&$!#*aLOP5sHIRg4R>p>2|W6`i`YuqTC@OcVWQxK^K>#6
z9GE9bUd{|Hr2o-drtL9d8nv~YxOX2LSZ3sdN$U?Yzp&hCtTVt{I8>s+;4*rBW=pCZ
zy))B!DGX+?#N`*AugVpUmhJp?<|xQV=8XG%`Zi6;XS?!wT;EpTLLKP9J{9f$h4qZm
z{*xeqzLTiTNn!Yp2R*ZV?tk}KTtcU?5rx*%aW3mqF&w73lM2Gmb>%U5O_Y>Fg7_=g
zw!-DX^ki)p0~Fzez6191Tjk9sy@SV*ELOvL<~2K`;qfrH+J=4NyR2jZ5YQp06Yu<1
zhkw#=lYgG&?I@(i!Cr#%1;9Vb&K7ZPN*WGrb)2$0)v;6#Xn}<ET_Fr&*KaKG$w|XG
zp8*>L*x49ICbz2KbAnqJn3+uGPmR4Lfp5Zt&c%YUY~f5*8kziBrODMb_TF<Wm>DZK
zP=_KUxm6@+nl6WP(;tqATiV@e9<subuf7DpLiNq1R__plj)ag;%6-M@g*bKGfq^#%
zYPbXFpk_KF2^|e%E{WF2mH1dd)zI4aP~Gx8%X)NpalpFN{FN&a_E9TD28*@pyUdz^
zMr@t<_&Q<^%|+DL&!!>l3RU}%jc<Tx3rYB@KyV3LEpFz_UI4a?hxL4-Vx9QHHvqVN
z6n<i{-%Ikxhx@%{7R3SCGX$>cJ!S(O8l0CYP7|$`$PFk3-hL1cyPvy+r3WhLdu*>|
zW_-^re7X{4asVpIP8se_N=WKeA@$T`ZNJQ_naX&nb;!>aFurn2i~%@je6O~smU4n>
z;I8V9V`62P)@_GJ(;iIBGiF6CM`kZ~2i}*12GZg#6{c}1PoAO};zy$v=<TMbDau~N
zmYD@NGyRh+EQyN|(%!ea`2|FxOIR7MG=s@8$?a<t&Zz_+2RU@sQaDV4lwX&=c`^u*
zZu++AqEYI8xN9Uty<y~&#W1Bn$Tw@QcKnQ#QWEKttzV2Q*gMg$qrLa5`*yfolZbG3
z$K`wM6O%iN1=d^fmYTGO2)wb_kg2U`uPA|L1Pf=;&fKnL)Q8ArPEXxi(BhY0XRn4n
z6j}-rF9u^t<&dSkBCaVJAzTIO4xhlc_XIELD|fsN%2mRhJH{QozENw%UBx=9%@$We
zGa5Q?k|BinhJL^OsM&bl(%kxWWd^u|ZFjykErq@ly7Qtv_QB(Rs`+NTy!x0TIACOi
zS+bh`pl}7p=5U46zr0gL5XASr{$&lj{ijp9g_6um0YB-+n`GPX)C#f=p<Ntb4Nd}?
zg%*CAYp{rk(n$>Cqzp=v0s?NmWcqbtXDfO&xieXPh0OZgxwthrg=t7B*($=Odf!px
zbxwz_uDk&agp5Vd)={{gtX)mwjNqZ#yUg}??nqnEV~9wibTs17&5*BDz;!+ec=~ZQ
zk|TJB>)p$WS{xYLoRBw<7MzC5L}Nk!;4WQice<MA?@_fISJVLiwH9na=pJB;1d&AA
zO^XkezZ`Nrq(d}o_E$34Z2k@Y5#zT*B;Qs99Hm9y3>qWR3NN?pzs5_+<*Yr<wEQs)
zI`2a^hMa521DlC0x}1TnB`#hD-j8`2U*&?ab-g~}w7ImFj)Sdl#GeBQ=vSrislT0#
z+kzG!9j&9Z5ck1S@zj3M_`_!(zh@UJmJB((d93cwUfFiQ{kvUs+jHS237zr=_YWh}
zCk(747S_jE|2b*<!pHADs<KncZUr~JYv0~^sF85^`P99jt7SATNHxgVDA4QY)z#PH
zg7?GW`Bd9JxxI19b}f(OIqMa>RRI+!kSG&sgi%dj75^yx<JZD`3|b8X^6Cb|^$3!+
zJ6&q07~(Ebu116!a}@lvzr@1xm!S;M$u^%Ze!cNCWFhrLVJ$k`D<c=hxbdNDpWdWI
z2IL#aL1@=ji!Hq=hAaWPvfKw@#mGYRtIFF>JgN|uenv*4zEX(_)2@5~$^*fAat4=?
zmJCECM@LJeRuF2;h{bf@i(%1J-(Jk@GTINv`70%nr!g{;>HX;vzysXd#HTq3)4rj?
zYg7RNLgR}9SKI$-*`fvto)BzT;)Jn9ze*IQlP`~s!i^zcd))XNH-HKnRv+LJbsn?t
z8HK^W$UftFXL&uP1Uy6J^gCU~D|9lWzM^{*8jHL$@}?^IGZh+bQ)A(yUYc?^2U=9E
zmLS5Q;*F*%9{i(=Xxtd`#rA4=uds@<&rIps3EXl9eSyQgM`s)NwXc&4&<BN}w5`9(
znuOW5dqRqwD>C0vZM=4gpV8|-yBOeAzc45&dj*?y+DXggeT(L>vAcP5mfW3|oPsCN
zMOr}^=w)e9smDlUJ23WjOYZFx+127{qced{IcqGynH%UtzG@Nrw9==^*o1s!C8mqf
z0R@jz4xEEUWOt@6z2ho8frUxX$atXWBC2psFD4zQp4bHa(VLbZJmF4`a3Wl0@QOK)
z**rR$_YjBD?ax!v;PzfYp<R&V$o9Vs1g(yb9$6P^rJ4Vk<wdcJI=Q>Yh=Cn~%<_RC
zaxMY-0s1OnO|jTNA9W3o#|q^h2=!VY(D5}vWSrn0Wu((J0A2PNsuSe<zFwR0<g}iH
z(KGGuFP1SoSsdj`g;8HqlI^K$tf07v@mXlqFS_Pmh{U;%-?xwpo<y=PP%<K?w;l;P
zu}y1%NasJPTD+S@b`1z9>l<ERi!=)QwyhhTE0=!P+nJpnvM015?Zd=;S$h6+8A+%R
zL<U?HX;B&ZjZ+E>3}R(Oa3S=-5$1h8NL#SdZCf79ozCC4N{y()4cwUDBO`gYvSPq9
zWQrxaxMnU>;8BTEa9LdcwX_pII5Ae@)M}takmo?R$>}g@qI?J4h!%))HqetPY4?e(
zHvVqr`HiBx>L@Qdx8gB(HlMH$vnl<9bv%gUI8(V1P-UAT9IHQ~$1AL(yxFq`NYyDS
z98p@8H(7qfL2xvTjd<*Ut8#0)U+=_kxsuu@%MrAR1UFA<r0LxH!5WT|<aOokgG~Q{
zu6{8N*RMu!X30ooC0Rb|ZN7CT+dg>i{DDCK24hJhg-kc?(veKxUpk8>Cut)gRsf<e
zdfDJ@q)<(^0Stn*x*EYPk3t-dyicn1=!XBzlzvq$;T||2aGi;7e!Pq&i`;^k2F6?u
zrY(dDi6)&lc(x}5?bNmBf{$|C7`j#hc~|*ZVdr2_Fk7AHGco&tPf!URy`%be+gBCD
zUMsXwBtOK!1cO~D5T2>peE28`DuP5ucxO(6;u6J_K@k*uki6_AY`W2+hZA)&9X>0(
zzKeo1u++H;T{AXiipelcmTId^m!sR0aQ<A|j7+RLvzzr0bO)^xv}8fp8r+WkY&gDz
ze>Nrmo$?m^xp8o#NE@FiJE;oqtx8ZFlF(gL<YVErLlX0Abo?r06&U?cDfZ7<{ga@?
zdzZg)ZdS6$xp0RrQ6Me2b@_R1YJX7hUl^hGmw{FODVLK{sM?2WYGz?jZyv<^%5;v(
z{J?+qJ4+k&pP;Jem%u%QfcGzXu23W^ti@H#*`8K}Mx?Ly#>JPeDwC%h0xZFQKA1I>
zLjA*Cq-w5@V#>M7suAJyG=6xA41^4QYK@5a@|=YbB9ocn!%s_LmYh}mctDbGoRkeq
zNf}BDZbXKRyPNnd&v_EJ1fnLc;Iw@9w`%z5d6V$_U*qk+#_w3j(dl(epgJk8fy*mo
zU75sQL3#o6-8;AlV(h3|^XoqK4Y=a)<z;g>pEG<k{KXQO><r#~?_48)^m<?3E=P3X
z_sW$Z<KFx%HnW{xC?mYbXBd64Ge2|Ua#oq*suD;~v@|Ux)HaF5zMy9dXfq&Bm)bVM
zt<L&8ozkoVq&p1bEBxrai&zbsbM89K4H?<v`(MG$OUf}<2Rhv@1|2b?OX*OvC5nAY
zmQZUeRRfT@Kcgrm;cdUXhE!kh9V*Y7&bXP61)mh|34<XxUo^l4udv)@?}KiY4m3SB
zm`=qx*V&7AI3u*dwcv-@2a*KGnx#f^#S#wa)EL3_SAD<n>(_(6JI=PZ**=k1wxilm
z9Wal<=v~Ba>wC-}p&ufZ?kAPL;Jw-|2cm;z7TW>rqn~#K@q9wsQkWm2i$O3TvT;Rf
z9fkKyJm(3bB%y<1V23k$7rhQ8+sH&=o9O(cV(#-K5ivPJ4HrB<2q_jT9}Dh?nDYd1
z_SgC3ks7J_kE(bD1)S5<v+}|{&F_kjKw5^=HI_DvC)Y?JXr7gaHL9H?Q0EJJoPRC|
zT)^GoI!c$w1a1FIeo1)tf_DV{MaJow$P5svt#YoA>BeW2-slUAxo@_h78dJ{kX+_z
z?L(99_xcVe&UbudGWSZX)DXMU-Z^gE`GUFbm`ve{>vfbM7jtjLKPvOpSWY8N7}gzO
zJFis(|6W2lAwC2eOVLp&^rRj1#6jdf?#<+%OdBbaIj;N^0x*W`49#6ns}&9&d2LD`
z4MA4U?OeT)sSYbt{9yX8H7XQaZ&Fgk#g%K?gY=F-S>IvyWf5I`yLCDqk7QS$k!-``
z=f<NB8^(0T2|stUxx+y2_zJF-_!S45;<xTmRNq-R^3d`xFgYFrX%yy?+t12yAwPYt
zh<*BMKzt*?!>tGM0!ks|z3Xu~Kq?lyMijGZg`2#8rjLpm{!v~;$Lo;A7vKQpa~7|x
z|M|cs+?V!8^-f?DJwloRSL$1XGz=Y1<V=uDK?rdXl~99*i0}*yP^v8}hs%ku6>=rz
zh7yv01kz_PqZdN(kUvQ5o2Z9^+LuIL-RUe;^~45a0Vnr2D)grQaq=PxQH4b|ScI$a
zK;tvb#ibEnh}+0m$R(a2?*uJdR8Bc5N&x1xsmKHhWV-9&Lds`&ewl(GwDA7|>CYzd
zr!gU0`9e&%zQrP7#ihW;Si-{?kew6AKNf2n18EcH{}j=e`M``YVqny@ZKH@Lb(CmV
z(VSA5Xe9F5?(DgGk>PiG#~GcSD)0Fp)4{D=2BS-~7Yd#*Fym=DwY;i#dA>`nGni)m
zb>!SJ7<=z);U!Ge#s)slrGv2wf9ms>zvO=v{vroN^8q9W|3h*cga80z(>J3B6UOq<
zkW=UP(ir?o37A^_(y8f*E9;|fbx4HN<PiMy=jq!c=ki5hEG)9Bo)RBVUl6Rs$t&ZA
z!aqM&H!3A^nPH*xR-{Zj?cHJCvvcdwB9iqKw&(3RfftMWp^|-IigTS!^yu&P=Ul=L
z5(elre-1g|x0;y_PtF{#gg$37!b33&L}H#4IYE!V6U~Dr!DL~}dgu<jnA6QZeeVEn
z37CX}e8q)*61)WYR@M~Vecx!9NuZnM2=h_8vnu{ZJtbFUlpYVKj=6;*2i+xqZBaTW
z;8rpdxo;S(E?#dN)1iEaM-o6rND6N2w3(e@Q*Bm?>?LM!7hdGwH;#rL&j#GV=z-kG
zfDiSX9F?ysRhkIjZ3~0kTL{Y5vBP|&=+TCCaIC(wdF~!3m@u#@WN%obit$R^ZLtpx
zrbgTi3+cqigU}&HPQ#RhZep?xR^E=DNOm#b8XAi|3+J??^K$O^QE6_7^swj9Vg2oR
z%RgC*#crm_5C$03){tu2aguK`<QAYq-;o}Ly+d1mth{N#rfR#ih`XbP?xxO9NugCI
z9ikd4B=1-}m4jQ*I-i%_zTe!#A-ds&%yD*9>w4U-p5~fltgCBn#|bG9SM%mHDb)Pc
z!CxuA8Lfkkk|1k}kH%-Dj&btV<A#0SKV0+qDXO%PwIka_g$4R9+?()UPPc8~DjFaK
z)eWe{yC`5`<s}rFuqar3{JG3RqXAc7YtX+CZVsw1VbTRSSY9vQHAe^|RfkA}_~737
zIno)o+GT_qpV|D=aD4uE@<7uWosjzrnGllQDRx3ET*x8$xl3)w4_+Y=?kswUU^Imt
z_DTi%|1Pz3S_wbhMAIW@jp^r&-STKn;T6ikkAe8(;T;#Kt!p5fPY5$d%x`d3R1-F$
z9@Xx{iwO7jX|2*N$TtpA3EoxH>)Buo$K*-s8OQEC{ez%-c9-e+l}N_1CHIJQ=^;A_
zj$K~_tL%o!Tt{cs9M`j@4mJg{_LjvR6yxUB1dhB*AgJo?&gX=VbF83!HXV<(i)Ovh
zk(iYjg3HV}oS)c4`_z`OwA_5%$p>EyAw%FeRg^$&<=P)-l70*e+c*Rl%HD+Yl&?w`
z^<|?Q4#_*|?AO5^=Y=zT-=WC$^SC1Jp!?S8RGJy7)Qz+|?T-jJX;d_x?QHHkwgHu)
zi?Mk`<lNXCN{gUX``)MTXe_pE&xVZ;K>fmqe|<{)QOi1;5WMAwF}0BMR}T>2rpFW<
zAGoHI6QVhQ>**A&+LJPiM(w8=DF+vYdwZNLNn3*Q+8V#Podgk*4|kfqW$snCqWijO
zxLx%q&;b+x84P{=IR&F1*W$R(#JTz&;5USnqO5%3DBX-iB`7^&jKFV%gv{)akZyN}
zyK=Ra(X|P1So!&>=9(QS-A9Q1T(l!BEmp;7$mePsU5osJ=|#Pu(Za6pBK1G1Jd7s%
zx2RlnbHeKSf7=C$!vD^AgckF~H2yaCFE)k3)}oY9ro1S}zu6<0+y4aza8pMUlKy{b
z%)rmU=VM8Xto)Uls`wACqP?DIZ3Uuy2wb7nzZNm?CR-IIJ>IL#mSa1P3mn8inEidx
z4?6QjUTbwtob#y&Uhtb+3>PT<`17Z@Ad7$Xi(N9+N%dd<T31K|F(C|w|BA+6m-@@9
zfBE`v82GOyFR})Df&c!p+~2?cyB+*jlZE^GcPlSa|NppsX!-pQD(^qb|KDu=KTj6w
z@!u)$Kg$2Vn*1M?_n&w0KfQe@UH;YY?R`%#NWOjKJG|CDI~!qO&rWO0Jaeb0{{?o)
BrJeu)

diff --git a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/Group.java b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/Group.java
index 30c155ce..a5dc8872 100644
--- a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/Group.java
+++ b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/Group.java
@@ -76,7 +76,8 @@ public class Group
      * Ctor.
      * 
      * @param groupID
-     *            Unique ID for the group
+     *            Unique ID for the group. Must be a valid URI fragment component,
+     *            so it's restricted to alphanumeric and "-", ".","_","~" characters.
      * @param owner
      *            Owner/Creator of the group.
      */
@@ -87,6 +88,12 @@ public class Group
         {
             throw new IllegalArgumentException("Null groupID");
         }
+        
+        // check for invalid path characters in groupID
+        if(!groupID.matches("^[a-zA-Z0-9\\-\\.~_]*$"))
+            throw new IllegalArgumentException("Invalid group ID " + groupID
+                    + ": may not contain space ( ), slash (/), escape (\\), or percent (%)");
+
         this.groupID = groupID;
         if(owner == null)
         {
diff --git a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/GroupProperty.java b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/GroupProperty.java
index 743af8e0..cee88725 100644
--- a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/GroupProperty.java
+++ b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/GroupProperty.java
@@ -140,9 +140,6 @@ public class GroupProperty
         final int prime = 31;
         int result = 1;
         result = prime * result + ((key == null) ? 0 : key.hashCode());
-        result = prime * result + (readOnly ? 1231 : 1237);
-        result = prime * result
-                + ((value == null) ? 0 : value.hashCode());
         return result;
     }
 
@@ -165,26 +162,7 @@ public class GroupProperty
             return false;
         }
         GroupProperty other = (GroupProperty) obj;
-        if (key == null)
-        {
-            if (other.key != null)
-            {
-                return false;
-            }
-        }
-        else if (!key.equals(other.key))
-        {
-            return false;
-        }
-        if (readOnly != other.readOnly)
-        {
-            return false;
-        }
-        if (!value.equals(other.value))
-        {
-            return false;
-        }
-        return true;
+        return key.equals(other.key);
     }
     
     @Override
diff --git a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/PosixDetails.java b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/PosixDetails.java
index ba6cf69f..44d8ff46 100644
--- a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/PosixDetails.java
+++ b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/PosixDetails.java
@@ -37,7 +37,7 @@ package ca.nrc.cadc.auth.model;
 /**
  * Represents the posix account details associated with a user account.
  */
-public class PosixDetails
+public class PosixDetails implements UserDetails
 {
     private long uid;
     private long gid;
diff --git a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/User.java b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/User.java
index 74ab9ad6..e92232c2 100644
--- a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/User.java
+++ b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/User.java
@@ -46,8 +46,7 @@ public class User<T extends Principal>
 
     private Set<Principal> principals = new HashSet<Principal>();
     
-    public UserDetails userDetails;
-    public PosixDetails posixDetails;
+    public Set<UserDetails> details = new HashSet<UserDetails>();
     
     
     public User(final T userID)
@@ -79,8 +78,7 @@ public class User<T extends Principal>
     {
         final int prime = 31;
         int result = 1;
-        result = prime * result
-                + ((userID == null) ? 0 : userID.hashCode());
+        result = prime * result + userID.hashCode();
         return result;
     }
 
diff --git a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/UserDetails.java b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/UserDetails.java
index dcede139..6720b0f8 100644
--- a/projects/cadcUtil/src/ca/nrc/cadc/auth/model/UserDetails.java
+++ b/projects/cadcUtil/src/ca/nrc/cadc/auth/model/UserDetails.java
@@ -34,169 +34,23 @@
 
 package ca.nrc.cadc.auth.model;
 
-public class UserDetails
+public interface UserDetails
 {
-    private String firstName;
-    private String lastName;
-    private String email;
-    private String address;
-    private String institute;
-    private String city;
-    private String country;
-
-    public UserDetails(String firstName, String lastName, String email,
-            String address, String institute, String city, String country)
-    {
-        if (firstName == null)
-        {
-            throw new IllegalArgumentException("null firstName");
-        }
-        if (lastName == null)
-        {
-            throw new IllegalArgumentException("null lastName");
-        }
-        if (email == null)
-        {
-            throw new IllegalArgumentException("null email");
-        }
-
-        if (address == null)
-        {
-            throw new IllegalArgumentException("null address");
-        }
-        if (institute == null)
-        {
-            throw new IllegalArgumentException("null institute");
-        }
-        if (city == null)
-        {
-            throw new IllegalArgumentException("null city");
-        }
-        if (country == null)
-        {
-            throw new IllegalArgumentException("null country");
-        }
-        this.firstName = firstName;
-        this.lastName = lastName;
-        this.email = email;
-        this.address = address;
-        this.institute = institute;
-        this.city = city;
-        this.country = country;
-    }
-
-    public String getFirstName()
-    {
-        return firstName;
-    }
-
-    public String getLastName()
-    {
-        return lastName;
-    }
-
-    public String getEmail()
-    {
-        return email;
-    }
-
-    public String getAddress()
-    {
-        return address;
-    }
-
-    public String getInstitute()
-    {
-        return institute;
-    }
-
-    public String getCity()
-    {
-        return city;
-    }
-
-    public String getCountry()
-    {
-        return country;
-    }
 
     /*
      * (non-Javadoc)
      * 
      * @see java.lang.Object#hashCode()
      */
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + address.hashCode();
-        result = prime * result + city.hashCode();
-        result = prime * result + country.hashCode();
-        result = prime * result + email.hashCode();
-        result = prime * result + firstName.hashCode();
-        result = prime * result + institute.hashCode();
-        result = prime * result + lastName.hashCode();
-        return result;
-    }
+    public int hashCode();
 
     /*
      * (non-Javadoc)
      * 
      * @see java.lang.Object#equals(java.lang.Object)
      */
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-        {
-            return true;
-        }
-        if (obj == null)
-        {
-            return false;
-        }
-        if (!(obj instanceof UserDetails))
-        {
-            return false;
-        }
-        UserDetails other = (UserDetails) obj;
-        if (!firstName.equals(other.firstName))
-        {
-            return false;
-        }
-        if (!lastName.equals(other.lastName))
-        {
-            return false;
-        }
-        if (!email.equals(other.email))
-        {
-            return false;
-        }
-        if (!institute.equals(other.institute))
-        {
-            return false;
-        }
-        if (!address.equals(other.address))
-        {
-            return false;
-        }
-        if (!city.equals(other.city))
-        {
-            return false;
-        }
-        if (!country.equals(other.country))
-        {
-            return false;
-        }
-        return true;
-    }
+    public boolean equals(Object obj);
+
+    public String toString();
 
-    @Override
-    public String toString()
-    {
-        return getClass().getSimpleName() + "[" + firstName + ", "
-                + lastName + ", " + email + ", " + address + ", "
-                + institute + ", " + city + ", " + country + "]";
-    }
-}
+}
\ No newline at end of file
diff --git a/projects/cadcUtil/test/src/ca/nrc/cadc/auth/model/GroupTest.java b/projects/cadcUtil/test/src/ca/nrc/cadc/auth/model/GroupTest.java
index 85c45dcb..3acb1a87 100644
--- a/projects/cadcUtil/test/src/ca/nrc/cadc/auth/model/GroupTest.java
+++ b/projects/cadcUtil/test/src/ca/nrc/cadc/auth/model/GroupTest.java
@@ -92,7 +92,7 @@ public class GroupTest
         assertEquals(group1.hashCode(), group2.hashCode());
         assertEquals(group1,group2);
         
-        group2 = new Group("NewTestGroup", owner);
+        group2 = new Group("NewTestGroup-._~.", owner);
         assertFalse(group1.hashCode() == group2.hashCode());
         assertFalse(group1.equals(group2));
         
@@ -125,5 +125,39 @@ public class GroupTest
             thrown = true;
         }
         assertTrue(thrown);
+        
+        // invavlid group IDs
+        thrown = false;
+        try
+        {
+            new Group("New/Test/Group", new User<HttpPrincipal>(new HttpPrincipal("owner")));
+        }
+        catch(IllegalArgumentException e)
+        {
+            thrown = true;
+        }
+        assertTrue(thrown);
+        
+        thrown = false;
+        try
+        {
+            new Group("New%Test%Group", new User<HttpPrincipal>(new HttpPrincipal("owner")));
+        }
+        catch(IllegalArgumentException e)
+        {
+            thrown = true;
+        }
+        assertTrue(thrown);
+        
+        thrown = false;
+        try
+        {
+            new Group("New\\Test\\Group", new User<HttpPrincipal>(new HttpPrincipal("owner")));
+        }
+        catch(IllegalArgumentException e)
+        {
+            thrown = true;
+        }
+        assertTrue(thrown);
     }
 }
diff --git a/projects/cadcUtil/test/src/ca/nrc/cadc/auth/model/UserTest.java b/projects/cadcUtil/test/src/ca/nrc/cadc/auth/model/UserTest.java
index 547b37d4..75f0dd92 100644
--- a/projects/cadcUtil/test/src/ca/nrc/cadc/auth/model/UserTest.java
+++ b/projects/cadcUtil/test/src/ca/nrc/cadc/auth/model/UserTest.java
@@ -65,8 +65,8 @@ public class UserTest
         assertEquals(user1, user2);
         assertEquals(user1.hashCode(), user2.hashCode());
 
-        user1.userDetails = new UserDetails("Joe", "Raymond",
-                "jr@email.com", "123 Street", "CADC", "Victoria", "CA");
+        user1.details.add(new PersonalDetails("Joe", "Raymond",
+                "jr@email.com", "123 Street", "CADC", "Victoria", "CA"));
         assertEquals(user1, user2);
         assertEquals(user1.hashCode(), user2.hashCode());
 
@@ -82,8 +82,8 @@ public class UserTest
         assertEquals(user1, user2);
         assertEquals(user1.hashCode(), user2.hashCode());
 
-        user1.posixDetails = new PosixDetails(12, 23,
-                "/home/myhome");
+        user1.details.add(new PosixDetails(12, 23,
+                "/home/myhome"));
         assertEquals(user1, user2);
         assertEquals(user1.hashCode(), user2.hashCode());
 
@@ -93,8 +93,9 @@ public class UserTest
         
         // visual test of toString
         System.out.println(user1);
-        System.out.println(user1.userDetails);
-        System.out.println(user1.posixDetails);
+        System.out.println(new PersonalDetails("Joe", "Raymond",
+                "jr@email.com", "123 Street", "CADC", "Victoria", "CA"));
+        System.out.println(new PosixDetails(12, 23,"/home/myhome"));
         
     }
     
@@ -115,7 +116,7 @@ public class UserTest
         thrown = false;
         try
         {
-            new UserDetails(null, "Raymond",
+            new PersonalDetails(null, "Raymond",
                     "jr@email.com", "123 Street", "CADC", "Victoria", "CA");
         }
         catch(IllegalArgumentException e)
@@ -127,7 +128,7 @@ public class UserTest
         thrown = false;
         try
         {
-            new UserDetails("Joe", null,
+            new PersonalDetails("Joe", null,
                     "jr@email.com", "123 Street", "CADC", "Victoria", "CA");
         }
         catch(IllegalArgumentException e)
@@ -139,7 +140,7 @@ public class UserTest
         thrown = false;
         try
         {
-            new UserDetails("Joe", "Raymond",
+            new PersonalDetails("Joe", "Raymond",
                     null, "123 Street", "CADC", "Victoria", "CA");
         }
         catch(IllegalArgumentException e)
@@ -151,7 +152,7 @@ public class UserTest
         thrown = false;
         try
         {
-            new UserDetails("Joe", "Raymond",
+            new PersonalDetails("Joe", "Raymond",
                     "jr@email.com", null, "CADC", "Victoria", "CA");
         }
         catch(IllegalArgumentException e)
@@ -163,7 +164,7 @@ public class UserTest
         thrown = false;
         try
         {
-            new UserDetails("Joe", "Raymond",
+            new PersonalDetails("Joe", "Raymond",
                     "jr@email.com", "123 Street", null, "Victoria", "CA");
         }
         catch(IllegalArgumentException e)
@@ -175,7 +176,7 @@ public class UserTest
         thrown = false;
         try
         {
-            new UserDetails("Joe", "Raymond",
+            new PersonalDetails("Joe", "Raymond",
                     "jr@email.com", "123 Street", "CADC", null, "CA");
         }
         catch(IllegalArgumentException e)
@@ -187,7 +188,7 @@ public class UserTest
         thrown = false;
         try
         {
-            new UserDetails("Joe", "Raymond",
+            new PersonalDetails("Joe", "Raymond",
                     "jr@email.com", "123 Street", "CADC", "Victoria", null);
         }
         catch(IllegalArgumentException e)
-- 
GitLab