Change username in Delphi RAD Server built-in Users Endpoint

463 views Asked by At

Im' using Delphi RAD Server 10.4 with patches 1,2 and 3 and I created endpoints to manage RAD users using authentication and security components TBackEndAuth and TBackendUser components.

I could SignUp a new user and LogIn sucessfully using these components, now I'm trying to update an user information but I can't manage an error when updating the field username.

See in the code the method UpdateUser. When run, it raises the error:

{ "error": "Error", "description": "EMS Error: Bad request. Operation could not be completed because one or more dynamic names conflicts with a static name. Conflict(s): username" }

If I comment the line lobjUser.AddPair('username',lusername_new); then it works fine. But I want to able to update the username too.

Any help is very welcome. Tks.

    unit DMUsermanager;

// EMS Resource Module

interface

uses
  System.SysUtils, System.Classes, System.JSON,
  EMS.Services, EMS.ResourceAPI, EMS.ResourceTypes, REST.Backend.ServiceTypes,
  REST.Backend.MetaTypes, REST.Backend.EMSServices, REST.Backend.Providers,
  REST.Backend.ServiceComponents, Data.Bind.Components, Data.Bind.ObjectScope,
  REST.Backend.BindSource, REST.Backend.EMSProvider;

type
  [ResourceName('UserManager')]
  TUsermanagerResource1 = class(TDataModule)
    EMSProvider1  : TEMSProvider;
    BackendAuth1  : TBackendAuth;
    BackendUsers1 : TBackendUsers;
  published

    [EndpointMethod(TEndpointRequest.TMethod.Post)]
    [ResourceSuffix('/SignUpUser')]
    procedure SignUpUser(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);

    [EndpointMethod(TEndpointRequest.TMethod.Post)]
    [ResourceSuffix('/LoginUser')]
    procedure LoginUser(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);


    [EndpointMethod(TEndpointRequest.TMethod.Post)]
    [ResourceSuffix('/UpdateUser')]
    procedure UpdateUser(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);

  end;

implementation

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}

procedure TUsermanagerResource1.SignUpUser(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
   lusername, lpassword                 : string;
   lcustomfieldemail, lcustomfieldage   : string;
   lcustomfields                        : TCollectionItem;
   jo                                   : TJSONObject;
begin
     if ARequest.Body.TryGetObject(jo) then
     begin
           // Get user data from JSON post request body
           lusername         := jo.GetValue<string>('username');
           lpassword         := jo.GetValue<string>('password');
           lcustomfieldemail := jo.GetValue<string>('email');
           lcustomfieldage   := jo.GetValue<string>('age');

           with BackEndAuth1 do
           begin
                 //Create CustomFields collection
                 UserDetails.Add;
                 UserDetails.Items[0].Name  := 'email';
                 UserDetails.Items[0].Value := lcustomfieldemail;

                 UserDetails.Add;
                 UserDetails.Items[1].Name  := 'age';
                 UserDetails.Items[1].Value := lcustomfieldage;

                 //Assign username and passowrd
                 UserName := lusername;
                 Password := lpassword;

                 //Creates the user in RAD Server
                 Signup;

                 // Check if creation was Ok and return user info
                 if LoggedIn then
                 begin
                      jo := TJSONObject.Create;
                      jo.AddPair('Username',LoggedInUserName);
                      jo.AddPair('Token'   ,LoggedInToken);
                      jo.AddPair('Email'   ,UserDetails[0].value);
                      jo.AddPair('Age'     ,UserDetails[1].value);
                      jo.AddPair('ID'      ,LoggedInValue.ObjectID);
                      AResponse.Body.SetValue(jo,true);
                 end
                 else
                     AResponse.RaiseBadRequest('Error on SignUp the user.');
           end;
     end
     else
         // JSON object content or format error
         AResponse.RaiseBadRequest('Error on request body JSONOBJECT.');
end;


procedure TUsermanagerResource1.LoginUser(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
   lusername, lpassword                 : string;
   jo                                   : TJSONObject;
begin
     if ARequest.Body.TryGetObject(jo) then
     begin
           // Get user credentials from JSON post request body
           lusername := jo.GetValue<string>('username');
           lpassword := jo.GetValue<string>('password');

           with BackEndAuth1 do
           begin
                 //Create CustomFields collection
                 UserDetails.Add;
                 UserDetails.Items[0].Name  := 'email';

                 UserDetails.Add;
                 UserDetails.Items[1].Name  := 'age';

                 //Assign username and passowrd
                 UserName := lusername;
                 Password := lpassword;

                 //Log in into RAD Server
                 Login;

                 // Check if Log in was Ok and return user info
                 if LoggedIn then
                 begin
                      jo := TJSONObject.Create;
                      jo.AddPair('Username',LoggedInUserName);
                      jo.AddPair('Token'   ,LoggedInToken);
                      jo.AddPair('Email'   ,UserDetails[0].value);
                      jo.AddPair('Age'     ,UserDetails[1].value);
                      jo.AddPair('ID'      ,LoggedInValue.ObjectID);
                      AResponse.Body.SetValue(jo,true);
                 end
                 else
                     AResponse.RaiseBadRequest('Error on Log in the user.');
           end;
     end
     else
         // JSON object content or format error
         AResponse.RaiseBadRequest('Error on request body JSONOBJECT.');
end;

procedure TUsermanagerResource1.UpdateUser(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
   lusername, lpassword                 : string;
   lusername_new, lpassword_new         : string;
   lcustomfieldemail, lcustomfieldage   : string;
   lcustomfields                        : TCollectionItem;
   jo, lobjUser                         : TJSONObject;
   lUpdatedAt                           : TBackendEntityValue;
begin
     if ARequest.Body.TryGetObject(jo) then
     begin
           // Get user data from JSON post request body
           lusername         := jo.GetValue<string>('username');
           lpassword         := jo.GetValue<string>('password');
           lusername_new     := jo.GetValue<string>('username_new');
           lpassword_new     := jo.GetValue<string>('password_new');
           lcustomfieldemail := jo.GetValue<string>('email');
           lcustomfieldage   := jo.GetValue<string>('age');

           with BackEndAuth1 do
           begin
                 //Assign username and passowrd
                 UserName := lusername;
                 Password := lpassword;

                 //Log in into RAD Server
                 Login;

                 if LoggedIn then
                 begin
                      //Create CustomFields collection
                      UserDetails.Add;
                      UserDetails.Items[0].Name  := 'email';
                      UserDetails.Items[0].Value := lcustomfieldemail;

                      UserDetails.Add;
                      UserDetails.Items[1].Name  := 'age';
                      UserDetails.Items[1].Value := lcustomfieldage;

                     // UserName := lusername_new;  ==> this does not work
                     // Password := lpassword_new;  ==> this does not work

                      //Updates user data in RAD Server
                      UpdateuserDetails;

                      lobjUser := TJSONObject.Create;
                      lobjUser.AddPair('username',lusername_new);  // this line is the ISSUE !!
                      lobjUser.AddPair('password',lpassword_new);

                      BackEndUsers1.Users.UpdateUser(LoggedInValue.ObjectID,lobjuser,lUpdatedAt);

                     // Check if creation was Ok and return user info
                     if LoggedIn then
                     begin
                          jo := TJSONObject.Create;
                          jo.AddPair('Username',LoggedInUserName);
                          jo.AddPair('Token'   ,LoggedInToken);
                          jo.AddPair('Email'   ,UserDetails[0].value);
                          jo.AddPair('Age'     ,UserDetails[1].value);
                          jo.AddPair('ID'      ,LoggedInValue.ObjectID);
                          AResponse.Body.SetValue(jo,true);
                     end
                     else
                         AResponse.RaiseBadRequest('Error on SignUp the user.');
                 end;
           end;
     end
     else
         // JSON object content or format error
         AResponse.RaiseBadRequest('Error on request body JSONOBJECT.');
end;


procedure Register;
begin
  RegisterResource(TypeInfo(TUsermanagerResource1));
end;

initialization
  Register;
end.

One more question : is this the right way to update user information in RAD Sever built-in users endpoint?

2

There are 2 answers

1
Fernando Rizzato On

I don't think an Username can be updated, but just the Custom Fields:

http://docwiki.embarcadero.com/RADStudio/Sydney/en/RAD_Server_Users_Resource#UpdateUser_Endpoint

0
Geoff Smith On

I have reported this as a bug in Quality portal. Vote for it to get it fixed

https://quality.embarcadero.com/browse/RSP-41163