...
Generate Digest Example Code
Code Block | ||
---|---|---|
| ||
package com.sunwave; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Base64; import java.util.TimeZone; import java.util.Date; import org.apache.commons.codec.digest.DigestUtils; public class DigestCreator { private String userId; private String clientId; private String clientSecret; // Realm Private Key "select client_secret from sw_external_application where client_id = ? and clinic_id = ? private String clinicId; private String transactionId; //"select id from sw_api_transaction where transaction_id = ? and clinic_id = ?" private String payload; private String createMd5Digest() throws NoSuchAlgorithmException, UnsupportedEncodingException { return Base64.getEncoder().encodeToString(DigestUtils.md5Hex(payload.getBytes()).getBytes()); } private String createSeed() throws NoSuchAlgorithmException, UnsupportedEncodingException { String seed = null; if (payload == null) { seed = userId + ":" + clientId + ":" + getDateTimeBase64() + ":" + clinicId + ":" + transactionId; } else { seed = userId + ":" + clientId + ":" + getDateTimeBase64() + ":" + clinicId + ":" + transactionId + ":" + createMd5Digest(); } return seed; } private String getDateTimeBase64() throws UnsupportedEncodingException { SimpleDateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); df.setTimeZone(TimeZone.getTimeZone("GMT")); Date d = new Date(); java.sql.Timestamp now = new java.sql.Timestamp(new java.util.Date().getTime()); String dateTime = df.format(now); byte[] encodedDate = Base64.getEncoder().encode(dateTime.getBytes()); return new String(encodedDate, "UTF8"); } private String createTransactionId() { return null; } private String createToken() throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException { if (payload == null) return userId + ":" + clientId + ":" + getDateTimeBase64() + ":" + clinicId + ":" + transactionId + ":" + createHMAC(createSeed()); else return userId + ":" + clientId + ":" + getDateTimeBase64() + ":" + clinicId + ":" + transactionId + ":" + createMd5Digest() + ":" + createHMAC(createSeed()); } private String createHMAC(String message) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException { byte[] byteKey = clientSecret.getBytes("UTF-8"); final String HMAC_SHA512 = "HmacSHA512"; Mac sha512_HMAC = Mac.getInstance(HMAC_SHA512); SecretKeySpec keySpec = new SecretKeySpec(byteKey, HMAC_SHA512); sha512_HMAC.init(keySpec); byte[] mac_data = sha512_HMAC. doFinal(message.getBytes("UTF-8")); return Base64.getUrlEncoder().encodeToString(mac_data); } public DigestCreator(String userId, String clientId, String clientSecret, String clinic_id, String transactionId, String payload) { this.userId = userId; this.clientId = clientId; this.clientSecret = clientSecret; this.clinicId = clinic_id; this.transactionId = transactionId; this.payload = payload; } public static void main( String args[] ) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException { if ((args.length < 5) || (args.length > 6)) { System.out.println("usage: java -cp . org.baudekin.DigestCreator user_id clinic_id client_id, client_secret, transaction_id, <pay load>"); System.exit(-1); } String payload = null; // We are doing post/* * Copyright 2023 Sunwave Health * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sunwave; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Base64; import java.util.TimeZone; import org.apache.commons.codec.digest.DigestUtils; public class DigestCreator { /** * userId is the email assigned to the user from sw_user_clinic.user_email. * If the combination of userId and clinic_id are not in sw_user_clinic * table the validation will fail. */ private final String userId; /** * clientId is the realm assigned to the user from * sw_user_clinic.clinic_id. If the combination of userId and clinic_id * are not in sw_user_clinic table the validation will fail. */ private final String clientId; /** * clinicId is the realm the user has permission to run rest calls against. */ private final String clinicId; /** * clientSecret is the secret key that was generated by the user's id and * clinic id. This comes from the sw_external_application table and is * used to calculate the HMAC. The HMAC the DigesterCreator calculates and * SunwaveEMR's DigestValidator must match. */ private final String clientSecret; /** * transactionId is a user chosen string that must be unique for the * whole clinic. This value is validated against the sw_api_transaction * table by transaction id and clinic id, the row is returned the * validation fails. */ private final String transactionId; /** * payload is only used on POST and PUT HTTP requests and is used to * calculate MD5 digest hash. */ private final String payload; /** * dateTime holds the current time in the following format * "Mon, 6 Feb 2023 16:35:45 +0000" as Base64 encoded string. This is * generated by getDateTimeBase64. ({@link #getDateTimeBase64()}) */ private final String dateTime; /** * PURPOSE: To calculate the MD5 digest of the payload and return the * lower case version of numeric digest as base 64 value. * @return Base64 value of the MD5 hash. * (@see <a href="https://en.wikipedia.org/wiki/MD5">MD5 Digest</a>) */ private String createMd5Digest() { byte[] digest = DigestUtils.md5Hex(payload.getBytes()).getBytes(); return Base64.getEncoder().encodeToString(digest); } /** * Purpose - To create the seed to be used with the user's private key to * generate the HMAC hash. In the case of GET HTTP requests the seed * comprises user id, client id, current time as Base64 string * {@link #dateTime}, clinic id and transaction id. In the case * of HTTP POST and PUT requests the MD5 digest of the payload is added * to the seed. * @return - Returns seed as clear text. */ private String createSeed() { String seed; if (args.lengthpayload == 6null) { payloadseed = args[5]; }userId + ":" + clientId + ":" + dateTime + ":" DigestCreator dc = new DigestCreator(args[0], args[2], args[3], args[1], args[4], payload); + clinicId + ":" + transactionId; System.out.println("Token: " + dc.createToken()); } else { System.out.println("md5 digest: " + dc.createMd5Digest()); seed = userId + ":" + clientId + ":" + dateTime + ":" System.exit(0); } + clinicId } | ||
Code Block | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>DigestCreater</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency>+ ":" + transactionId + ":" + createMd5Digest(); } return seed; } /** <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> * PURPOSE: To generate Base64 of the current timestamp. The format is <version>1.15</version> * "Mon, 6 </dependency>Feb 2023 </dependencies> <build> 16:42:14 +0000" Note it is using GMT <plugins> * the local +0000 <plugin>to generate the timestamp. <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId>* @return - Current time as Base64 string. */ <version>3.4.2</version> private String getDateTimeBase64() { <executions> SimpleDateFormat df = <execution> new SimpleDateFormat("EEE, d MMM yyyy <phase>package</phase>HH:mm:ss Z"); df.setTimeZone(TimeZone.getTimeZone("GMT")); <goals> java.sql.Timestamp now = <goal>single</goal> new java.sql.Timestamp(new java.util.Date().getTime()); </goals> String currentTime = df.format(now); <configuration> byte[] encodedDate = <archive> Base64.getEncoder().encode(currentTime.getBytes()); return new String(encodedDate, StandardCharsets.UTF_8); <manifest> } /** * Purpose: Create the digest <mainClass>token that can be used in Authorization Head * key with value of Digest concatenated com.sunwave.DigestCreatorwith token: * "Digest sunwave-admin1:vQl91X514m11dTHHGYQPQ ...". The token consists of </mainClass>* user id, client id, current date time, clinic id, transaction id </manifest>* HMAC code in the case of HTTP Get Request. For HTTP PUT and POST </archive>the * token consists of user id, client id, <descriptorRefs>current date time, clinic id, * transaction id, MD5 digest of <descriptorRef>jar-with-dependencies</descriptorRef> the payload and HMAC code. * (@see <a </descriptorRefs>href="https://en.wikipedia.org/wiki/Digest_access_authentication">Digest Authentication</a>) * @return - digest token </configuration> * @throws NoSuchAlgorithmException - Handles the message signature </execution>of * {@link </executions>#createHMAC(String)} * @throws </plugin>InvalidKeyException - Handles the message signature of <plugin> * {@link #createHMAC(String)} <groupId>org.apache.maven.plugins</groupId> */ <artifactId>maven-compiler-plugin</artifactId> private String createToken() throws NoSuchAlgorithmException, <configuration> InvalidKeyException { <source>8</source> if (payload == null) { <target>8</target> </configuration>return userId + ":" + clientId </plugin>+ ":" + dateTime + ":" + clinicId </plugins> </build> </project> |
Generate GET Request Digest
Code Block |
---|
java -cp ./target/DigestCreater-1.0-SNAPSHOT.jar com.sunwave.DigestCreator sunwave-admin1 131 vQl91X514m11dTHHGYQPQkxJqNPxgbdJ C0iGincSREijXqeuB3P9sDdj1ZU6UwqVaUc6VLwhpcx2sBQmB85k8zWuIKSc6gkCAcnXm4JTk2YBFpH5fFDEPH0JyKg4SgchallGmNDc9fNkO1ojZxyKaZ5murQZFDvSW7iJl1CM5JESube8P0cdlqtiLoHb7BP4293S6FqG557TbIPS61ACp0lfAOu9fNXD6L2LD24j7QMRZpM8GE6GQOnY5nTaHGn42eBMjB8iMS9gx4P7iStJirC0vjq2miSC 0000002 |
...
Generate POST Request Digest
Data Dictionary
...
Term
...
Definition
+ ":" + transactionId + ":" + createHMAC(createSeed());
} else {
return userId + ":" + clientId + ":" + dateTime + ":" + clinicId
+ ":" + transactionId + ":" + createMd5Digest() + ":"
+ createHMAC(createSeed());
}
}
/**
* Purpose: Create Base 64 encoded HMAC hash-based message authentication
* code (@see <a href="https://en.wikipedia.org/wiki/HMAC">HMAC</a>).
* Sunwave uses the SHA-512 Secure Hash Algorithm 2
* (@see <a href="https://en.wikipedia.org/wiki/SHA-2">SHAR-512</a>).
* @param seed - The seed string to generate the HMAC on.
* @return - HMAC Code as BAse 64 encoded String.
* @throws NoSuchAlgorithmException - When Mac class does not support
* the give hashing algorithm. Note it support HmacSHA512 so no problem.
* @throws InvalidKeyException - {@link #clientSecret} key can not be
* used by the SecretKeySpec class.
*/
private String createHMAC(final String seed)
throws NoSuchAlgorithmException, InvalidKeyException {
byte[] byteKey = clientSecret.getBytes(StandardCharsets.UTF_8);
final String hmacSha512 = "HmacSHA512";
Mac sha512Hmac = Mac.getInstance(hmacSha512);
SecretKeySpec keySpec = new SecretKeySpec(byteKey, hmacSha512);
sha512Hmac.init(keySpec);
byte[] macData = sha512Hmac.
doFinal(seed.getBytes(StandardCharsets.UTF_8));
return Base64.getUrlEncoder().encodeToString(macData);
}
/**
* Purpose: Create DigestCreator object populated with all the information
* to generate digest authentication token.
* @param userId - {@link #userId}
* @param clientId - {@link #clientId}
* @param clientSecret - {@link #clientSecret}
* @param clinicId - {@link #clinicId}
* @param transactionId - {@link #transactionId}
* @param payload - {@link #payload}
*/
public DigestCreator(final String userId, final String clientId,
final String clientSecret, final String clinicId,
final String transactionId, final String payload) {
this.userId = userId;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.clinicId = clinicId;
this.transactionId = transactionId;
this.payload = payload;
this.dateTime = getDateTimeBase64();
}
/**
* Purpose: Provides command line interface to generate digest
* authentication token.
* @param args - Command line parameters.
*/
public static void main(final String[] args) {
if ((args.length < 5) || (args.length > 6)) {
System.out.println("java -cp ./target/DigestCreator-1.0-SNAPSHOT.jar com.sunwave.DigestCreator [user_id] [clinic_id] [client_id] [client_secret] [transaction_id] <payload>");
System.out.println("java -cp ./target/DigestCreator-1.0-SNAPSHOT.jar com.sunwave.DigestCreator sunwave-admin1 131 vQl91X514m11dTHHGYQPQkxJqNPxgbdJ C0iGincSREijXqeuB3P9sDdj1ZU6UwqVaUc6VLwhpcx2sBQmB85k8zWuIKSc6gkCAcnXm4JTk2YBFpH5fFDEPH0JyKg4SgchallGmNDc9fNkO1ojZxyKaZ5murQZFDvSW7iJl1CM5JESube8P0cdlqtiLoHb7BP4293S6FqG557TbIPS61ACp0lfAOu9fNXD6L2LD24j7QMRZpM8GE6GQOnY5nTaHGn42eBMjB8iMS9gx4P7iStJirC0vjq2miSC 0000002");
System.exit(-1);
}
String payload = null;
// We are doing post
if (args.length == 6) {
payload = args[5];
}
DigestCreator dc = new DigestCreator(args[0], args[2], args[3], args[1], args[4], payload);
try {
System.out.println("Token: " + dc.createToken());
} catch (Exception e) {
System.err.println("Unable to create authentication token.");
e.printStackTrace(System.err);
System.exit(-2);
}
System.exit(0);
}
}
|
Code Block |
---|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>DigestCreater</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>
com.sunwave.DigestCreator
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project> |
Generate GET Request Digest
Code Block |
---|
java -cp ./target/DigestCreater-1.0-SNAPSHOT.jar com.sunwave.DigestCreator sunwave-admin1 131 vQl91X514m11dTHHGYQPQkxJqNPxgbdJ C0iGincSREijXqeuB3P9sDdj1ZU6UwqVaUc6VLwhpcx2sBQmB85k8zWuIKSc6gkCAcnXm4JTk2YBFpH5fFDEPH0JyKg4SgchallGmNDc9fNkO1ojZxyKaZ5murQZFDvSW7iJl1CM5JESube8P0cdlqtiLoHb7BP4293S6FqG557TbIPS61ACp0lfAOu9fNXD6L2LD24j7QMRZpM8GE6GQOnY5nTaHGn42eBMjB8iMS9gx4P7iStJirC0vjq2miSC 0000002 |
...
Generate POST Request Digest
Code Block | ||
---|---|---|
| ||
#!/usr/bin/env bash
TRANSACTION_ID=$1
#PAYLOAD="eyJjYWxsZXJfZmlyc3RfbmFtZSIgOiAiQXBpLTEwIiwgImNhbGxlcl9sYXN0X25hbWUiIDogIkFwaS0xMCIsICJwYXRpZW50X2ZpcnN0X25hbWUiIDogIkFwaS0xMCIsICJwYXRpZW50X2xhc3RfbmFtZSIgOiAiQXBpLTEwIiwgInBhdGllbnRfZGF0ZV9vZl9iaXJ0aCIgOiAiMTk4MC0wNC0wNCIsICJhY2NvdW50X2lkIjogIjQzMSIsICJzY2hlZHVsZWRfc2VydmljZV9mYWNpbGl0eV9pZCIgOiAiMTIzNCIsICJzY2hlZHVsZWRfYWRtaXNzaW9uX2RhdGUiIDogIjIwMjItMTAtMDgiLCAic2NoZWR1bGVkX2FkbWlzc2lvbl90aW1lIjogIjA5OjAwIiwgInNjaGVkdWxlZF9sZXZlbF9vZl9jYXJlX2lkIjogIjEiLCAic2NoZWR1bGVkX3Byb2dyYW0iOiAiMTA2NSIsICJwYXRpZW50X3Bob25lX21vYmlsZSI6ICI3ODY0Mzg4Nzg2IiwgInBhdGllbnRfcGhvbmVfd29yayI6ICI3ODY0Mzg4Nzg2IiwgInBhdGllbnRfcGhvbmVfaG9tZSI6ICI3ODY0Mzg4Nzg2IiwgInBhdGllbnRfc3NuIjogIjQ1NS02Ni02Njc3IiwgInBhdGllbnRfZW1haWwiOiAiYXBpLTZAZ21haWwuY29tIiwgInBhdGllbnRfYWRkcmVzcyI6ICIzMzc1IFcgNzZTdCIsICJwYXRpZW50X2NpdHkiOiAiTWlhbWkiLCAicGF0aWVudF9zdGF0ZSI6ICJGTCIsICJwYXRpZW50X3ppcCI6ICIzMzAxOSIsICJwYXRpZW50X2dlbmRlcl9jb2RlIjogIk0iLCAicmFjZSI6ICJJbmRpYW4iLCAibWFya2V0aW5nX3NvdXJjZV9jb250YWN0X2lkIjogIjM2IiwgImFkbWlzc2lvbl9yZXByZXNlbnRhdGl2ZSI6ICIyNzAxNiIsICJpbnN1cmFuY2VfcHJvdmlkZXIiOiAiOTc0IiwgIm1lbWJlcl9pZCI6ICIxMTIyIiwgImluc3VyYW5jZV9ncm91cF9udW1iZXIiOiAiMzAwMCIsICJzY2hlZHVsZWRfaW50YWtlX21lc3NhZ2UiOiAiTmVlZCB0byBwYXkifQo="
PAYLOAD='{"caller_first_name" : "Api-10", "caller_last_name" : "Api-10", "patient_first_name" : "Api-10", "patient_last_name" : "Api-10", "patient_date_of_birth" : "1980-04-04", "account_id": "431", "scheduled_service_facility_id" : "1234", "scheduled_admission_date" : "2022-10-08", "scheduled_admission_time": "09:00", "scheduled_level_of_care_id": "1", "scheduled_program": "1065", "patient_phone_mobile": "7864388786", "patient_phone_work": "7864388786", "patient_phone_home": "7864388786", "patient_ssn": "455-66-6677", "patient_email": "api-6@gmail.com", "patient_address": "3375 W 76St", "patient_city": "Miami", "patient_state": "FL", "patient_zip": "33019", "patient_gender_code": "M", "race": "Indian", "marketing_source_contact_id": "36", "admission_representative": "27016", "insurance_provider": "974", "member_id": "1122", "insurance_group_number": "3000", "scheduled_intake_message": "Need to pay"}'
# {
# "caller_first_name" : "Api-10",
# "caller_last_name" : "Api-10",
# "patient_first_name" : "Api-10",
# "patient_last_name" : "Api-10",
# "patient_date_of_birth" : "1980-04-04",
# "account_id": "431",
# "scheduled_service_facility_id" : "1234",
# "scheduled_admission_date" : "2022-10-08",
# "scheduled_admission_time": "09:00",
# "scheduled_level_of_care_id": "1",
# "scheduled_program": "1065",
# "patient_phone_mobile": "7864388786",
# "patient_phone_work": "7864388786",
# "patient_phone_home": "7864388786",
# "patient_ssn": "455-66-6677",
# "patient_email": "api-6@gmail.com",
# "patient_address": "3375 W 76St",
# "patient_city": "Miami",
# "patient_state": "FL",
# "patient_zip": "33019",
# "patient_gender_code": "M",
# "race": "Indian",
# "marketing_source_contact_id": "36",
# "admission_representative": "27016",
# "insurance_provider": "974",
# "member_id": "1122",
# "insurance_group_number": "3000",
# "scheduled_intake_message": "Need to pay"
#}
java -jar ./target/DigestCreater-1.0-SNAPSHOT-jar-with-dependencies.jar sunwave-admin1 131 vQl91X514m11dTHHGYQPQkxJqNPxgbdJ C0iGincSREijXqeuB3P9sDdj1ZU6UwqVaUc6VLwhpcx2sBQmB85k8zWuIKSc6gkCAcnXm4JTk2YBFpH5fFDEPH0JyKg4SgchallGmNDc9fNkO1ojZxyKaZ5murQZFDvSW7iJl1CM5JESube8P0cdlqtiLoHb7BP4293S6FqG557TbIPS61ACp0lfAOu9fNXD6L2LD24j7QMRZpM8GE6GQOnY5nTaHGn42eBMjB8iMS9gx4P7iStJirC0vjq2miSC "${TRANSACTION_ID}" "${PAYLOAD}" |
Code Block |
---|
source ./postgen.sh test00013 |
...
Data Dictionary
Term | Definition |
---|---|
Client Id | The unique identifier we assign to user of external API call. Random 32 character string generated using custom algorithm. https://github.com/sunwavehealth/SunwaveEMR/blob/d46b653451ce24623a0c6c72d0aa4e2313c5c0f9/src/main/java/com/sunwave/emr/server/security/ExternalApplicationProcessor.java#L96 |
Client Secret | Secret we assign to the user of the Rest API. It is 256 characters randomly generated by custom algorithm. https://github.com/sunwavehealth/SunwaveEMR/blob/d46b653451ce24623a0c6c72d0aa4e2313c5c0f9/src/main/java/com/sunwave/emr/server/security/ExternalApplicationProcessor.java#L96 |
User Id | The use’s account for Sunwave Health. I It must have an email to be used for this validation. |
Clinic Id | Realm to the user id is to be validated against. |
Transaction Id | A unique id the customer generates for each transaction. Can not be reused. |
Payload | Only used for POST operations and is the base 64 encoded string representing the data to be put into Sunwave. |
MD5 Digest | Message-digest algorithm for producing 128-bit hash values. See https://en.wikipedia.org/wiki/MD5 Sunwave uses it as a checksum to validate the request has not been modified. |
Seed | For GET requests: |
HMAC | Hash Based Method Authentication code see https://en.wikipedia.org/wiki/HMAC Used to verify both the data integrity and authenticity of the user’s request. |
Token | This is the string to used as the Digest. |
...
Code Block | ||
---|---|---|
| ||
##### Begin GET Validation Trace 01 Feb 2023 10:21:01,666~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.server.security.DigestValidator::validateTransactionId line: 79 01 Feb 2023 10:21:01,671~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ select id from sw_api_transaction where transaction_id = '0000002' and clinic_id = '131' 01 Feb 2023 10:21:08,263~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.server.security.DigestValidator::validateTransactionId line: 84 01 Feb 2023 10:21:08,265~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ insert into sw_api_transaction (transaction_id, created_on,clinic_id) values ('0000002',str_to_date('2023-02-01 10:21:06','%Y-%m-%d %H:%i:%s'),'131') 01 Feb 2023 10:22:09,078~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.server.security.DigestValidator::validateGET line: 52 01 Feb 2023 10:22:09,081~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ select user_email from sw_user_clinic where sw_user_clinic.clinic_id = '131' and sw_user_clinic.user_email = 'sunwave-admin1' 01 Feb 2023 10:22:12,955~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.server.security.DigestValidator::getPrivateKey line: 73 01 Feb 2023 10:22:12,959~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ select client_secret from sw_external_application where client_id = 'vQl91X514m11dTHHGYQPQkxJqNPxgbdJ' and clinic_id = '131' ##### End GET Validation Trace ##### Begin GET Users Trace 01 Feb 2023 10:23:55,725~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.server.security.APISecurityFilter::validateAPICalls line: 198 01 Feb 2023 10:23:55,726~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ select api_call_limit_per_day from sw_clinic where clinic_id = '131' 01 Feb 2023 10:23:55,739~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.server.security.APISecurityFilter::validateAPICalls line: 200 01 Feb 2023 10:23:55,739~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ select call_log_count from sw_api_call_count_log where call_log_date = '2023-02-01' and clinic_id = '131' 01 Feb 2023 10:23:55,747~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.server.security.APISecurityFilter::validateAPICalls line: 207 01 Feb 2023 10:23:55,747~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ update sw_api_call_count_log set call_log_count = call_log_count + 1 where call_log_date = '2023-02-01' and clinic_id = '131' 01 Feb 2023 10:23:55,757~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.server.Processor::getParentClinicId line: 1535 01 Feb 2023 10:23:55,757~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ SELECT parent_clinic_id FROM sw_clinic where clinic_id='131' 01 Feb 2023 10:23:55,762~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.server.Processor::getTimezoneId line: 1584 01 Feb 2023 10:23:55,762~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ SELECT timezone_id, clinic_id FROM sw_clinic where id='131' 01 Feb 2023 10:23:55,768~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:37 ~ ~ *********** com.sunwave.emr.dao.UserDao::getUsersByClinicExcludingSunwaveUsers line: 763 01 Feb 2023 10:23:55,768~ DEBUG ~ com.sunwave.emr.server.util.LoggerUtils:38 ~ ~ SELECT mb2_user.id, mb2_user.email, mb2_user.first_name, mb2_user.last_name, ifnull(mb2_user.created_on,sw_user_clinic.created_on) created_on, mb2_user.created_by, if(sw_user_clinic.last_login='2011-01-01 00:00:00', '', sw_user_clinic.last_login) last_login FROM mb2_user inner join sw_user_clinic on sw_user_clinic.user_email = mb2_user.email WHERE sw_user_clinic.clinic_id='131'user_clinic.clinic_id='131' and ((mb2_user.is_sunwave != 'true' and mb2_user.is_sunwave_user != 'true') or and ((mb2_user.is_sunwave != 'true'is null and mb2_user.is_sunwave_user != 'true'is null)) or ##### End GET (mb2_user.is_sunwave is null and mb2_user.is_sunwave_user is null)) ##### End GET Users Trace Users Trace |
Validate API Calls aka limit the number of times the user can use the rest endpoints