IdUserAccounts.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.5 10/26/2004 10:51:40 PM JPMugaas
  18. Updated ref.
  19. Rev 1.4 7/6/2004 4:53:46 PM DSiders
  20. Corrected spelling of Challenge in properties, methods, types.
  21. Rev 1.3 2004.02.03 5:44:40 PM czhower
  22. Name changes
  23. Rev 1.2 2004.01.22 2:05:16 PM czhower
  24. TextIsSame
  25. Rev 1.1 1/21/2004 4:21:08 PM JPMugaas
  26. InitComponent
  27. Rev 1.0 11/13/2002 08:04:16 AM JPMugaas
  28. }
  29. unit IdUserAccounts;
  30. {
  31. Original Author: Sergio Perry
  32. Date: 24/04/2001
  33. 2002-05-03 - Andrew P.Rybin
  34. - TIdCustomUserManager,TIdSimpleUserManager,UserId
  35. - universal TIdUserManagerAuthenticationEvent> Sender: TObject
  36. }
  37. interface
  38. {$i IdCompilerDefines.inc}
  39. uses
  40. Classes,
  41. IdGlobal,
  42. IdBaseComponent,
  43. IdComponent;
  44. type
  45. TIdUserHandle = UInt32;//ptr,object,collection.item.id or THandle
  46. TIdUserAccess = Integer; //<0-denied, >=0-accept; ex: 0-guest,1-user,2-power user,3-admin
  47. var
  48. IdUserHandleNone: TIdUserHandle = High(UInt32)-1; //Special handle: empty handle
  49. IdUserHandleBroadcast: TIdUserHandle = High(UInt32); //Special handle
  50. IdUserAccessDenied: TIdUserAccess = Low(Integer); //Special access
  51. type
  52. TIdCustomUserManagerOption = (umoCaseSensitiveUsername, umoCaseSensitivePassword);
  53. TIdCustomUserManagerOptions = set of TIdCustomUserManagerOption;
  54. TIdUserManagerAuthenticationEvent = procedure(Sender: TObject; {TIdCustomUserManager, TIdPeerThread, etc}
  55. const AUsername: String;
  56. var VPassword: String;
  57. var VUserHandle: TIdUserHandle;
  58. var VUserAccess: TIdUserAccess) of object;
  59. TIdUserManagerLogoffEvent = procedure(Sender: TObject; var VUserHandle: TIdUserHandle) of object;
  60. TIdCustomUserManager = class(TIdBaseComponent)
  61. protected
  62. FDomain: String;
  63. FOnAfterAuthentication: TIdUserManagerAuthenticationEvent; //3
  64. FOnBeforeAuthentication: TIdUserManagerAuthenticationEvent;//1
  65. FOnLogoffUser: TIdUserManagerLogoffEvent;//4
  66. //
  67. procedure DoBeforeAuthentication(const AUsername: String; var VPassword: String;
  68. var VUserHandle: TIdUserHandle; var VUserAccess: TIdUserAccess); virtual;
  69. // Descendants must override this method:
  70. procedure DoAuthentication (const AUsername: String; var VPassword: String;
  71. var VUserHandle: TIdUserHandle; var VUserAccess: TIdUserAccess); virtual; abstract;
  72. procedure DoAfterAuthentication (const AUsername: String; var VPassword: String;
  73. var VUserHandle: TIdUserHandle; var VUserAccess: TIdUserAccess); virtual;
  74. procedure DoLogoffUser(var VUserHandle: TIdUserHandle); virtual;
  75. function GetOptions: TIdCustomUserManagerOptions; virtual;
  76. procedure SetDomain(const AValue: String); virtual;
  77. procedure SetOptions(const AValue: TIdCustomUserManagerOptions); virtual;
  78. // props
  79. property Domain: String read FDomain write SetDomain;
  80. property Options: TIdCustomUserManagerOptions read GetOptions write SetOptions;
  81. // events
  82. property OnBeforeAuthentication: TIdUserManagerAuthenticationEvent
  83. read FOnBeforeAuthentication write FOnBeforeAuthentication;
  84. property OnAfterAuthentication: TIdUserManagerAuthenticationEvent
  85. read FOnAfterAuthentication write FOnAfterAuthentication;
  86. property OnLogoffUser: TIdUserManagerLogoffEvent read FOnLogoffUser write FOnLogoffUser;
  87. public
  88. //Challenge user is a nice backdoor for some things we will do in a descendent class
  89. function ChallengeUser(var VIsSafe : Boolean; const AUserName : String) : String; virtual;
  90. function AuthenticateUser(const AUsername, APassword: String): Boolean; overload;
  91. function AuthenticateUser(const AUsername, APassword: String; var VUserHandle: TIdUserHandle): TIdUserAccess; overload;
  92. class function IsRegisteredUser(AUserAccess: TIdUserAccess): Boolean;
  93. procedure LogoffUser(AUserHandle: TIdUserHandle); virtual;
  94. procedure UserDisconnected(const AUser : String); virtual;
  95. function SendsChallange : Boolean; virtual;
  96. End;//TIdCustomUserManager
  97. //=============================================================================
  98. // * TIdSimpleUserManager *
  99. //=============================================================================
  100. TIdSimpleUserManager = class(TIdCustomUserManager)
  101. protected
  102. FOptions: TIdCustomUserManagerOptions;
  103. FOnAuthentication: TIdUserManagerAuthenticationEvent;
  104. //
  105. procedure DoAuthentication (const AUsername: String; var VPassword: String;
  106. var VUserHandle: TIdUserHandle; var VUserAccess: TIdUserAccess); override;
  107. function GetOptions: TIdCustomUserManagerOptions; override;
  108. procedure SetOptions(const AValue: TIdCustomUserManagerOptions); override;
  109. published
  110. property Domain;
  111. property Options;
  112. // events
  113. property OnBeforeAuthentication;
  114. property OnAuthentication: TIdUserManagerAuthenticationEvent read FOnAuthentication write FOnAuthentication;
  115. property OnAfterAuthentication;
  116. property OnLogoffUser;
  117. End;//TIdSimpleUserManager
  118. //=============================================================================
  119. // * TIdUserManager *
  120. //=============================================================================
  121. const
  122. IdUserAccountDefaultAccess = 0;//guest
  123. type
  124. TIdUserManager = class;
  125. TIdUserAccount = class(TCollectionItem)
  126. protected
  127. FAttributes: TStrings;
  128. // When ARC is enabled, object references MUST be valid objects.
  129. // It is common for users to store non-object values, though, so
  130. // we will provide separate properties for those purposes
  131. //
  132. // TODO; use TValue instead of separating them
  133. //
  134. FDataObject: TObject;
  135. FDataValue: PtrInt;
  136. //
  137. FUserName: string;
  138. FPassword: string;
  139. FRealName: string;
  140. FAccess: TIdUserAccess;
  141. //
  142. procedure SetAttributes(const AValue: TStrings);
  143. procedure SetPassword(const AValue: String); virtual;
  144. public
  145. constructor Create(ACollection: TCollection); override;
  146. destructor Destroy; override;
  147. //
  148. function CheckPassword(const APassword: String): Boolean; virtual;
  149. //
  150. property DataObject: TObject read FDataObject write FDataObject;
  151. property DataValue: PtrInt read FDataValue write FDataValue;
  152. {$IFNDEF USE_OBJECT_ARC}
  153. property Data: TObject read FDataObject write FDataObject; // deprecated 'Use DataObject or DataValue property.';
  154. {$ENDIF}
  155. published
  156. property Access: TIdUserAccess read FAccess write FAccess default IdUserAccountDefaultAccess;
  157. property Attributes: TStrings read FAttributes write SetAttributes;
  158. property UserName: string read FUserName write FUserName;
  159. property Password: string read FPassword write SetPassword;
  160. property RealName: string read FRealName write FRealName;
  161. End;//TIdUserAccount
  162. TIdUserAccounts = class(TOwnedCollection)
  163. protected
  164. FCaseSensitiveUsernames: Boolean;
  165. FCaseSensitivePasswords: Boolean;
  166. //
  167. function GetAccount(const AIndex: Integer): TIdUserAccount;
  168. function GetByUsername(const AUsername: String): TIdUserAccount;
  169. procedure SetAccount(const AIndex: Integer; AAccountValue: TIdUserAccount);
  170. public
  171. function Add: TIdUserAccount; reintroduce;
  172. constructor Create(AOwner: TIdUserManager);
  173. //
  174. property CaseSensitiveUsernames: Boolean read FCaseSensitiveUsernames
  175. write FCaseSensitiveUsernames;
  176. property CaseSensitivePasswords: Boolean read FCaseSensitivePasswords
  177. write FCaseSensitivePasswords;
  178. property UserNames[const AUserName: String]: TIdUserAccount read GetByUsername; default;
  179. property Items[const AIndex: Integer]: TIdUserAccount read GetAccount write SetAccount;
  180. end;//TIdUserAccounts
  181. TIdUserManager = class(TIdCustomUserManager)
  182. protected
  183. FAccounts: TIdUserAccounts;
  184. //
  185. procedure DoAuthentication (const AUsername: String; var VPassword: String;
  186. var VUserHandle: TIdUserHandle; var VUserAccess: TIdUserAccess); override;
  187. function GetOptions: TIdCustomUserManagerOptions; override;
  188. procedure SetAccounts(AValue: TIdUserAccounts);
  189. procedure SetOptions(const AValue: TIdCustomUserManagerOptions); override;
  190. public
  191. constructor Create(AOwner: TComponent); override;
  192. destructor Destroy; override;
  193. published
  194. property Accounts: TIdUserAccounts read FAccounts write SetAccounts;
  195. property Options;
  196. // events
  197. property OnBeforeAuthentication;
  198. property OnAfterAuthentication;
  199. End;//TIdUserManager
  200. implementation
  201. uses
  202. SysUtils;
  203. { How add UserAccounts to your component:
  204. 1) property UserAccounts: TIdCustomUserManager read FUserAccounts write SetUserAccounts;
  205. 2) procedure SetUserAccounts(const AValue: TIdCustomUserManager);
  206. begin
  207. if FUserAccounts <> AValue then begin
  208. if Assigned(FUserAccounts) then begin
  209. FUserAccounts.RemoveFreeNotification(Self);
  210. end;
  211. FUserAccounts := AValue;
  212. if Assigned(FUserAccounts) then begin
  213. FUserAccounts.FreeNotification(Self);
  214. end;
  215. end;
  216. end;
  217. 3) procedure Notification(AComponent: TComponent; Operation: TOperation);
  218. begin
  219. ...
  220. if (Operation = opRemove) and (AComponent = FUserAccounts) then begin
  221. FUserAccounts := nil;
  222. end;
  223. ...
  224. inherited Notification(AComponent, Operation);
  225. end;
  226. 4) ... if Assigned(FUserAccounts) then begin
  227. FAuthenticated := FUserAccounts.AuthenticateUser(FUsername, ASender.UnparsedParams);
  228. if FAuthenticated then else
  229. }
  230. { TIdCustomUserManager }
  231. function TIdCustomUserManager.AuthenticateUser(const AUsername, APassword: String): Boolean;
  232. var
  233. LUserHandle: TIdUserHandle;
  234. Begin
  235. Result := IsRegisteredUser(AuthenticateUser(AUsername, APassword, LUserHandle));
  236. LogoffUser(LUserHandle);
  237. End;//AuthenticateUser
  238. function TIdCustomUserManager.AuthenticateUser(const AUsername, APassword: String; var VUserHandle: TIdUserHandle): TIdUserAccess;
  239. var
  240. LPassword: String;
  241. Begin
  242. LPassword := APassword;
  243. VUserHandle := IdUserHandleNone;
  244. Result := IdUserAccessDenied;
  245. DoBeforeAuthentication(AUsername, LPassword, VUserHandle, Result);
  246. DoAuthentication(AUsername, LPassword, VUserHandle, Result);
  247. DoAfterAuthentication(AUsername, LPassword, VUserHandle, Result);
  248. End;//
  249. class function TIdCustomUserManager.IsRegisteredUser(AUserAccess: TIdUserAccess): Boolean;
  250. Begin
  251. Result := AUserAccess>=0;
  252. End;
  253. procedure TIdCustomUserManager.DoBeforeAuthentication(const AUsername: String; var VPassword: String;
  254. var VUserHandle: TIdUserHandle; var VUserAccess: TIdUserAccess);
  255. Begin
  256. if Assigned(FOnBeforeAuthentication) then begin
  257. FOnBeforeAuthentication(SELF,AUsername,VPassword,VUserHandle,VUserAccess);
  258. end;
  259. End;//
  260. procedure TIdCustomUserManager.DoAfterAuthentication(const AUsername: String; var VPassword: String;
  261. var VUserHandle: TIdUserHandle; var VUserAccess: TIdUserAccess);
  262. Begin
  263. if Assigned(FOnAfterAuthentication) then begin
  264. FOnAfterAuthentication(SELF,AUsername,VPassword,VUserHandle,VUserAccess);
  265. end;
  266. End;//
  267. function TIdCustomUserManager.GetOptions: TIdCustomUserManagerOptions;
  268. Begin
  269. Result := [];
  270. End;//
  271. procedure TIdCustomUserManager.SetOptions(const AValue: TIdCustomUserManagerOptions);
  272. Begin
  273. End;
  274. procedure TIdCustomUserManager.SetDomain(const AValue: String);
  275. begin
  276. if FDomain<>AValue then begin
  277. FDomain := AValue;
  278. end;
  279. end;
  280. procedure TIdCustomUserManager.LogoffUser(AUserHandle: TIdUserHandle);
  281. Begin
  282. DoLogoffUser(AUserHandle);
  283. End;//free resources, unallocate handles, etc...
  284. //=============================================================================
  285. procedure TIdCustomUserManager.DoLogoffUser(var VUserHandle: TIdUserHandle);
  286. Begin
  287. if Assigned(FOnLogoffUser) then begin
  288. FOnLogoffUser(SELF, VUserHandle);
  289. end;
  290. End;//
  291. function TIdCustomUserManager.ChallengeUser(var VIsSafe : Boolean;
  292. const AUserName: String): String;
  293. begin
  294. VIsSafe := True;
  295. Result := '';
  296. end;
  297. procedure TIdCustomUserManager.UserDisconnected(const AUser: String);
  298. begin
  299. end;
  300. function TIdCustomUserManager.SendsChallange : Boolean;
  301. begin
  302. Result := False;
  303. end;
  304. { TIdUserAccount }
  305. function TIdUserAccount.CheckPassword(const APassword: String): Boolean;
  306. begin
  307. if (Collection as TIdUserAccounts).CaseSensitivePasswords then begin
  308. Result := Password = APassword;
  309. end else begin
  310. Result := TextIsSame(Password, APassword);
  311. end;
  312. end;
  313. constructor TIdUserAccount.Create(ACollection: TCollection);
  314. begin
  315. inherited Create(ACollection);
  316. FAttributes := TStringList.Create;
  317. FAccess := IdUserAccountDefaultAccess;
  318. end;
  319. destructor TIdUserAccount.Destroy;
  320. begin
  321. FAttributes.Free;
  322. inherited Destroy;
  323. end;
  324. procedure TIdUserAccount.SetAttributes(const AValue: TStrings);
  325. begin
  326. FAttributes.Assign(AValue);
  327. end;
  328. procedure TIdUserAccount.SetPassword(const AValue: String);
  329. begin
  330. FPassword := AValue;
  331. end;
  332. { TIdUserAccounts }
  333. constructor TIdUserAccounts.Create(AOwner: TIdUserManager);
  334. begin
  335. inherited Create(AOwner, TIdUserAccount);
  336. end;
  337. function TIdUserAccounts.GetAccount(const AIndex: Integer): TIdUserAccount;
  338. begin
  339. Result := TIdUserAccount(inherited Items[AIndex]);
  340. end;
  341. function TIdUserAccounts.GetByUsername(const AUsername: String): TIdUserAccount;
  342. var
  343. i: Integer;
  344. begin
  345. Result := nil;
  346. if CaseSensitiveUsernames then begin
  347. for i := 0 to Count - 1 do begin
  348. if AUsername = Items[i].UserName then begin
  349. Result := Items[i];
  350. Break;
  351. end;
  352. end;
  353. end
  354. else begin
  355. for i := 0 to Count - 1 do begin
  356. if TextIsSame(AUsername, Items[i].UserName) then begin
  357. Result := Items[i];
  358. Break;
  359. end;
  360. end;
  361. end;
  362. end;
  363. procedure TIdUserAccounts.SetAccount(const AIndex: Integer; AAccountValue: TIdUserAccount);
  364. begin
  365. inherited SetItem(AIndex, AAccountValue);
  366. end;
  367. function TIdUserAccounts.Add: TIdUserAccount;
  368. begin
  369. Result := inherited Add as TIdUserAccount;
  370. end;
  371. { IdUserAccounts - Main Component }
  372. constructor TIdUserManager.Create(AOwner: TComponent);
  373. begin
  374. inherited Create(AOwner);
  375. FAccounts := TIdUserAccounts.Create(Self);
  376. end;
  377. destructor TIdUserManager.Destroy;
  378. begin
  379. FAccounts.Free;
  380. inherited Destroy;
  381. end;
  382. procedure TIdUserManager.DoAuthentication(const AUsername: String; var VPassword: String;
  383. var VUserHandle: TIdUserHandle; var VUserAccess: TIdUserAccess);
  384. var
  385. LUser: TIdUserAccount;
  386. begin
  387. VUserHandle := IdUserHandleNone;
  388. VUserAccess := IdUserAccessDenied;
  389. LUser := Accounts[AUsername];
  390. if Assigned(LUser) then begin
  391. if LUser.CheckPassword(VPassword) then begin
  392. VUserHandle := LUser.ID;
  393. VUserAccess := LUser.Access;
  394. end;
  395. end;
  396. end;
  397. procedure TIdUserManager.SetAccounts(AValue: TIdUserAccounts);
  398. begin
  399. FAccounts.Assign(AValue);
  400. end;
  401. function TIdUserManager.GetOptions: TIdCustomUserManagerOptions;
  402. Begin
  403. Result := [];
  404. if FAccounts.CaseSensitiveUsernames then begin
  405. Include(Result, umoCaseSensitiveUsername);
  406. end;
  407. if FAccounts.CaseSensitivePasswords then begin
  408. Include(Result, umoCaseSensitivePassword);
  409. end;
  410. End;//
  411. procedure TIdUserManager.SetOptions(const AValue: TIdCustomUserManagerOptions);
  412. Begin
  413. FAccounts.CaseSensitiveUsernames := umoCaseSensitiveUsername in AValue;
  414. FAccounts.CaseSensitivePasswords := umoCaseSensitivePassword in AValue;
  415. End;//
  416. { TIdSimpleUserManager }
  417. procedure TIdSimpleUserManager.DoAuthentication(const AUsername: String; var VPassword: String;
  418. var VUserHandle: TIdUserHandle; var VUserAccess: TIdUserAccess);
  419. Begin
  420. if Assigned(FOnAuthentication) then begin
  421. FOnAuthentication(SELF,AUsername,VPassword,VUserHandle,VUserAccess);
  422. end;
  423. End;//
  424. function TIdSimpleUserManager.GetOptions: TIdCustomUserManagerOptions;
  425. Begin
  426. Result := FOptions;
  427. End;//
  428. procedure TIdSimpleUserManager.SetOptions(
  429. const AValue: TIdCustomUserManagerOptions);
  430. Begin
  431. FOptions := AValue;
  432. End;//
  433. end.