Create user (with Aurelius) and set initial password?

Hi,

I have changed my Sphinx server to a Windows service and all works great. For use in my XData server (now a service application too), I have created an extended user entity (TSpinxUserEx) with an additional field.

As it is now a service, I am trying to build a simple VCL application that uses Aurelius to access the Sphinx database so that I can manage users from the backoffice. This too works OK (the newuser can enter user name and does receive the email confirmation token as designed/expected.

The final step is where the problem is: I cannot seem to find out how I can set an initial password for the user (only using Aurelius, i.e. not having an IUserManager available). Is this possible and if so/not how can I best achieve this?

Hi,

Ideally you should use Sphinx classes, more specifically in this case, IUserManager, to handle the uses in the database.

You can use it from a VCL Aurelius application, you don't need to use from a Sphinx server. So my suggestion is that in your VCL application you simply use IUserManager to handle the user in a safer and higher-level way.

Clear, but how do get the IUserManager? If my memory serves me right, you normally get it from the SphinxContext (which obviously isn't there in a VCL Aurelius application)?

You can create the context yourself just calling TSphinxContext.Create, there are several overloads:

  TSphinxContext = class(TInterfacedObject, ISphinxContext)
  public
    constructor Create(AOptions: ICoreOptions; APool: IDBConnectionPool); overload;
    constructor Create(AOptions: ICoreOptions; AUserManagerFactory: IUserManagerFactory; APool: IDBConnectionPool); overload;
    constructor Create(AOptions: ICoreOptions; AManager: TObjectManager; AOwnsManager: Boolean = True); overload;
    constructor Create(AOptions: ICoreOptions; AUserManagerFactory: IUserManagerFactory; AManager: TObjectManager; AOwnsManager: Boolean = True); overload;

Alternatively you can also just create the IUserManager interface directly using TUserManager.Create:

  TUserManager = class(TInterfacedObject, IUserManager)
  public
    constructor Create(AConfig: ICoreOptions; AManager: TObjectManager; AOwnsManager: boolean = False);

You can see that the only parameter that you might be wondering how to pass is the ICoreOptions interface. That you can obtain from an existing TSphinxConfig component (e.g., SphinxConfig1, this way:

uses {...}, Sphinx.ConfigCoreOptions;

var
  CoreOptions: ICoreOptions;
begin
  CoreOptions := TConfigCoreOptions.Create(SphinxConfig1);

We have added a service to the Sphinx Server application to allow us to manage users. Locked down with lots of attributes and secondary validation of course

What kind of service? Do you mean an XData service (interface) or a Windows service?

Are you willing to share some details on how you implemented it? I just need to manage users from the back office (direct access to server) so an Aurelius/VCL application - in principle - is sufficient for me. Nevertheless, I am curious to other "flavors" that could be applied...

It is an XData service built into our Sphinx Authenticator App, that enables our management app to create and update users.

All our services descend from a base class that implements (among lots of other useful methods/properties)

property SphinxManager: TObjectManager read GetSphinxManager;
property SphinxContext: ISphinxContext read GetSphinxContext;

//...

function TsmxSphinxServerBase.GetSphinxContext: ISphinxContext;
begin
  if not Assigned(FSphinxContext) then
  begin
     FSphinxContext := TSphinxContext.Create(TConfigCoreOptions.Create(FSphinxConfig),
         TXDataOperationContext.Current.GetConnectionPool);
  end;
  Result := FSphinxContext;
end;

function TsmxSphinxServerBase.GetSphinxManager: TObjectManager;
begin
  if not Assigned(FSphinxManager) then
  begin
    if FNeedsContext then
      FSphinxManager := (SphinxContext as TSphinxContext).Manager
    else
      FSphinxManager := TObjectManager.Create(DBConnection, TMappingExplorer.Get(cSphinxModelName));
  end;

  Result := FSphinxManager;
end;

FSphinxConfig is a class var.

We also have another service for our multitenant systems that allows tenant admins to manage their own users.

In reaction to Wagner's example on creating the ICoreOptions, I found that some additional units are required in the uses clause. As it took some time to find them (:slight_smile:), I am posting this - working - example. Perhaps it's of use for other users as a reference:

uses Sphinx.CoreOptions, Sphinx.ConfigCoreOptions, Sphinx.UserManager, Sphinx.UserManager.Impl, 
Entities.SphinxUserEx; // Unit implementing an extended user class

procedure TForm1.MyButtonClick(Sender: TObject);
var
  CoreOptions: ICoreOptions;
  UsrMgr: IUserManager;
  Usr: TSphinxUserEx;
begin
  CoreOptions := TConfigCoreOptions.Create(SphinxConfig);
  UsrMgr := TUserManager.Create(CoreOptions, FObjMgr, false);
  Usr := UsrMgr.FindByEmail('name@domain.com') as TSphinxUserEx; // Cast to custom class!
  if assigned(Usr) then
    // Access_Level is property added in extended user class
    showMessage('User: ' + Usr.UserName.Value + sLineBreak + 'Email: ' + Usr.Email.Value + sLineBreak + 'Access level: ' + Usr.Access_Level) 
  else
    showMessage('User not found!');
1 Like