Specifying multiple "implementation=" tags in #requestbody openapi tag in quarkus REST api - rest

I have a quarkus REST api that accepts JSON strings (various kinds) as events and then propagates them to a KAFKA topic.
I want to now put the structure of the possible JSON strings in the openAPI contract (without having to type it out myself manually.
I have managed to find the #requestbody tag that allows me to specify the one structure but I have multiple types of events that all have to go to the same Kafka topic.
example:
#POST
#Path("/student")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Tag(name = "Student Events Service")
#Operation(summary = "Accepts student type events", description = "Accepts student type events")
#APIResponse(responseCode = "200", description = "Event sent successfully")
#APIResponse(responseCode = "400", description = "The JSON packet sent did not conform to any known message or the primary key or shared data in the packet is invalid. \n "
+ "See Response Body for detail. - "
+ "Error code 400-1 = Bad message structure or unknown message. Log error and continue to next message - "
+ "Error code 400-2 = Bad primary key. Fix data (client or server side) and retry later - "
+ "Error code 400-3 = Invalid shared data. Fix shared data and retry later",
content = #Content(mediaType = "application/json",
schema = #Schema(implementation = ErrorResponse.class)))
#APIResponse(responseCode = "500", description = "Unexpected server error. See Response Body for detail. - "
+ "Error code 500-1 = Unable to send to KAFKA, please wait and retry later - "
+ "Error code 500-2 = Unable to connect to verification database, please wait and retry later - "
+ "Error code 500-3 = General server error, Please wait and retry later",
content = #Content(mediaType = "application/json",
schema = #Schema(implementation = ErrorResponse.class)))
public Response postStudentEvent(String eventJSON) {
Now I can put the following tag in to generate the openapi contract for 1 class of eventJSON string
#RequestBody(
required = true,
content = #Content(
schema = #Schema(implementation = Application.class)
)
)
But lets say I also want to be able to accept JSON string with the structure of CourseEnrollment.class (These classes are all part of the project btw).
public class CourseEnrollment {
private String eventID;
private String eventTime;
private String eventType;
private String eventUserSource;
private String externalReference1;
private String firstName;
private String lastName;
private String emailAddressPrimary;
private String emailAddressAlternate;
private String periodStartDate;
private String periodEndDate;
private String intakeIntakeYearCode;
private String programmeCode;
public class Application {
private String eventID;
private String eventTime;
private String eventType;
private String eventUserSource;
private String eventTrigger;
private ApplicationInfo applicationDetails = null;
private Person personDetails = null;
private School schoolDetails = null;
Its a wierd scenario I know, but thats what I have to deal with as we have an external system generating the events and sending the JSON to my REST service and I have to propagate the JSON to the KAFKA topics locally.
Thank you for your inputs

You can use oneOf:
#RequestBody(
required = true,
content = #Content(
schema = #Schema(oneOf = {Application.class, CourseEnrollment.class})
)
)

Related

Agora Always token expired when using unity Token generators

I make video chatting use agora
https://docs.agora.io/en/video-calling/develop/integrate-token-generation?platform=unity
I made it by following the guide above.
Play UnityEditor and Create a token with a token generator and start join channel.
But Channel Join is fail and I receive "Error code:109 msg:channel key expired"
It's a new token make by token generator, but I don't know why it's being expired.
sombody help me. thx.
private string appId = "my_agora_consone_appId";
private string appCertificate = "my_agora_consone_appCertificate ";
private string channelName = "vdch57";
private string uid = UserInfo.Instance.userKey.ToString();
private string userAccount = "User account";
private int expirationTimeInSeconds = 3600;
public string MakeToken(string channelName)
{
AccessToken token = new AccessToken(appId, appCertificate, channelName, uid);
string token2 = SignalingToken.getToken(appId, appCertificate, userAccount, expirationTimeInSeconds);
token.addPrivilege(Privileges.kJoinChannel, Convert.ToUInt32(expirationTimeInSeconds));
string result = token.build();
return result;
}

Is there a way to register a data asset in Azure Data Catalog via api without user-login?

My app gets a token and can make api calls to the ADC like searching. But the request for registration of new asset fails, because the field "LastRegisterdBy" must not be null/empty and has to correspond to current user.
However the token does not contain any user information (AccessToken().Result.UserInfo.DisplayableId is null).
I mostly followed the get started get-started project MS provides (https://github.com/Azure-Samples/data-catalog-dotnet-get-started/blob/master/Program.cs)
But i use
AcquireTokenAsync(resourceUri, clientCredential).ConfigureAwait(false)
instead of
AcquireTokenAsync(resourceUri, clientId, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Always)).
This so nobody has to enter his credentials. The goal is to run the code in ssis package, which will execute on a weekly basis to catch any updates in the data automatically.
This is the outline of my code:
class Program
{
static string clientIDFromAzureAppRegistration = "";
static string clientSecret = "";
static AuthenticationResult authResult = null;
static string catalogName = "catalog";
static void Main(string[] args)
{
var authResult = AccessToken();
string upn = authResult.Result.UserInfo.DisplayableId;
var id = RegisterDataAsset(authResult, SampleJson("test", upn));
}
static async Task<AuthenticationResult> AccessToken()
{
if (authResult == null)
{
//Resource Uri for Data Catalog API
string resourceUri = "https://api.azuredatacatalog.com";
//To learn how to register a client app and get a Client ID, see https://msdn.microsoft.com/en-us/library/azure/mt403303.aspx#clientID
string clientId = clientIDFromAzureAppRegistration;
string clientS = clientSecret;
// Create an instance of AuthenticationContext to acquire an Azure access token
var authority = "https://login.microsoftonline.com/52497ec2-0945-4f55-8021-79766363dd96";
var authContext = new AuthenticationContext(authority);
var clientCredential = new ClientCredential(clientId, clientS);
// Call AcquireToken to get an Azure token from Azure Active Directory token issuance endpoint
// AcquireToken takes a Client Id that Azure AD creates when you register your client app.
authResult = await authContext.AcquireTokenAsync(resourceUri, clientCredential).ConfigureAwait(false);
}
return authResult;
}
static string RegisterDataAsset(Task<AuthenticationResult> authResult, string json){
...
}
static HttpWebResponse SetRequestAndGetResponse(HttpWebRequest request, Task<AuthenticationResult> authResult, string payload = null){
...
}
static string SampleJson(string name, string upn){
...}
With upn = authResult.Result.UserInfo.DisplayableId; i get:
{"error":{"code":"InvalidPropertyValue","message":"Invalid input value for one of the properties. Path: 'properties.lastRegisteredBy.upn'. Details: Value cannot be null, empty or consists entirely of whitespaces."}}
Wit upn = "test#user":
{"error":{"code":"InvalidLastRegisteredBy","message":"LastRegisteredBy is different from the current user."}}
I found the solution, its quite simple:
The user-name of the app is: clientIDFromAzureAppRegistration + "#" + tenantId.

Creating a Signed URL for Google Cloud Storage

We have an ERP application running on GCP .
For downloading data spanning more than three months or so ,we're uploading a file on GCS. Now i want to create a signed url so that to give limited access to the end users .
I have been trying this. But i get this error :
Signature does not match. Please check your Google secret key.
Can anyone tell how to go about this?
private static final int EXPIRATION_TIME = 5;
private static final String BASE_URL = "https://storage.googleapis.com";
private static final String httpVerb = "GET";
/*
* private static final String BUCKET = "my_bucket"; private static final String
* FOLDER = "folder";
*/
private final AppIdentityService identityService = AppIdentityServiceFactory.getAppIdentityService();
public String getSignedUrl(String bucket, final String fileName, String contentTpe) throws Exception {
final long expiration = expiration();
final String unsigned = stringToSign(bucket, expiration, fileName, contentTpe);
final String signature = sign(unsigned);
return new StringBuilder(BASE_URL).append("/").append(bucket).append("/").append(fileName)
.append("?GoogleAccessId=").append(clientId()).append("&Expires=").append(expiration)
.append("&Signature=").append(URLEncoder.encode(signature, "UTF-8")).toString();
}
private static long expiration() {
final long unitMil = 1000l;
final Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, EXPIRATION_TIME);
final long expiration = calendar.getTimeInMillis() / unitMil;
return expiration;
}
private String stringToSign(String bucket, final long expiration, String filename, String contentType) {
final String contentMD5 = "";
final String canonicalizedExtensionHeaders = "";
final String canonicalizedResource = "/" + bucket + "/" + filename;
final String stringToSign = httpVerb + "\n"+ contentMD5 + "\n" + contentType + "\n" + expiration + "\n"
+ canonicalizedExtensionHeaders + canonicalizedResource;
return stringToSign;
}
protected String sign(final String stringToSign) throws UnsupportedEncodingException {
final SigningResult signingResult = identityService.signForApp(stringToSign.getBytes());
final String encodedSignature = new String(Base64.encodeBase64(signingResult.getSignature()), "UTF-8");
return encodedSignature;
}
protected String clientId() {
return identityService.getServiceAccountName();
}
URL signing code is a bit tricky because by its nature it can be difficult to know what you've gotten wrong, other than just seeing that it's wrong. There are a few general tips that make it easier:
First, if possible, consider using URL signing functions in the google-cloud libraries. For example, the Java google-cloud library provides a Storage.signURL method, and you can use it like this:
URL signedUrl = storage.signUrl(
BlobInfo.newBuilder(bucketName, blobName).build(),
2, TimeUnit.DAYS);
Second, if you look at the error message, you'll notice that there's a <StringToSign> section. This section contains the exact string that GCS would calculate a signature for. Make sure that the string you're signing matches this string exactly. If it doesn't, that's your problem.
In your code's particular case, I didn't find the problem, but it might be that you're including a content-type line when signing the string, but GET requests don't provide a Content-Type header. It's just an idea, though, since I don't see your invocation of getSignedUrl.

Spring 4 Restfull Service with bean

I am trying to create a simple Server / Client application that can send a bean as parameter instead of String but failing below is my code
Server
#Controller
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping(method=RequestMethod.POST,value="/returnGreet")
public #ResponseBody Greeting returnGreet(
#RequestBody(required=false) Greeting greet) {
if(greet == null)
return new Greeting(counter.incrementAndGet(),
String.format(template, greet));
else
return new Greeting(0,"Testing");
}
}
Client
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String,Greeting> greet = new LinkedMultiValueMap<String, Greeting>();
greet.add("greet", new Greeting(0,"XOXO"));
greeting = restTemplate.postForObject("http://localhost:8080/returnGreet",greet, Greeting.class,greet);
System.out.println("Content: " + greeting.getContent());
System.out.println("Id: " + greeting.getId() );
The result is always null for the object greet at the server side.
Any Idea ?
You're not using the RestTemplate correctly. Why are you passing a MultiValueMap as the Entity to be sent? This won't get serialized the way your Server expects.
Just use the Greeting object directly.
restTemplate.postForObject("http://localhost:8080/returnGreet", new Greeting(0, "XOXO"), Greeting.class);
Also, the last argument is not necessary, you don't have any URI variables.

How to retrieve all the Groups/Roles a user is member of using SOAP services?

I am trying to collect some user informations using SOAP services.
I was able to get the Job Title for a given user, but I don't understand how to retrieve the list of groups and roles that a user has.
Can I simply use the GroupServiceSoap.getUserPlaces(long userId, String[] classNames, int max) method? Or is there another way I can get these fields?
Currently my code:
private static URL _getURL(String remoteUser, String password, String serviceName) {
final String LIFERAY_PROTOCOL = "http://";
final String LIFERAY_TCP_PORT = "8080";
final String LIFERAY_FQDN = "localhost";
final String LIFERAY_AXIS_PATH = "/api/secure/axis/";
try {
return new URL(LIFERAY_PROTOCOL + URLEncoder.encode(remoteUser, "UTF-8") + ":"
+ URLEncoder.encode(password, "UTF-8") + "#" + LIFERAY_FQDN
+ ":" + LIFERAY_TCP_PORT + LIFERAY_AXIS_PATH + serviceName);
} catch (MalformedURLException e) {
return null;
} catch (UnsupportedEncodingException e) {
return null;
}
}
[...]
public static void main(String[] argv){
public final String LIFERAY_USER_SERVICE="Portal_UserService";
public final String LIFERAY_COMPANY_SERVICE="Portal_CompanyService";
public final String LIFERAY_GROUP_SERVICE = "Portal_GroupService";
//company.default.web.id property
public final String LIFERAY_DEFAULT_COMPANY_ID = "liferay.com";
UserServiceSoap userService = new UserServiceSoapServiceLocator().getPortal_UserService(_getURL(USER_IDENTIFIER,USER_PASSWORD, LIFERAY_USER_SERVICE));
//This code is usefull if you want to use SOAP setter.
//((Portal_UserServiceSoapBindingStub) userService).setUsername(USER_IDENTIFIER);
//((Portal_UserServiceSoapBindingStub) userService).setPassword(USER_PASSWORD);
CompanyServiceSoap companyService = new CompanyServiceSoapServiceLocator().getPortal_CompanyService(_getURL(USER_IDENTIFIER, USER_PASSWORD, LIFERAY_COMPANY_SERVICE));
long companyId = companyService.getCompanyByMx(LIFERAY_DEFAULT_COMPANY_ID).getCompanyId();
// Here I retrieve my user, and can access some properties, but not them all !
UserSoap user = userService.getUserByEmailAddress(companyId, target_user_mail);
//TODO : I got hte JobTittle that I want, later I will do something more util thant just print it, I swear it my precious !
System.out.println(user.getJobTitle());
GroupServiceSoap groupService = new GroupServiceSoapServiceLocator().getPortal_GroupService(_getURL(USER_IDENTIFIER, USER_PASSWORD, LIFERAY_GROUP_SERVICE));
//this one return an empty array
GroupSoap[] userPlaces = groupService.getUserPlaces(new String[]{"Group", "Role"}, 150);
//this return an array of size 1, but the only GroupSoap seems to be a structural groups without any usefull properties to me.
GroupSoap[] userPlaces = groupService.getUserPlaces(null, 150);
}
Use this method to get user role and group user id
UserServiceSoap.getRoleUserIds
UserServiceSoap.getGroupUserIds
HTH
It is only a partial answer.
In order to get all the User Roles one can do this :
RoleServiceSoap roleService = new RoleServiceSoapServiceLocator().getPortal_RoleService(_getURL(USER_IDENTIFIER, USER_PASSWORD, LIFERAY_ROLE_SERVICE));
RoleSoap[] userRoles = roleService.getUserRoles(user.getUserId());
with user variable an instance of UserSoap.
The SOAP access must be done by an Admin user in order to get access to the Role List. The user can't access this himself.