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?
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