Added api service
This commit is contained in:
parent
ccb0161609
commit
cd0f4bccd9
5
.gitignore
vendored
5
.gitignore
vendored
@ -36,4 +36,7 @@ __pycache__
|
||||
.pytest_cache
|
||||
|
||||
### Parser ###
|
||||
parser/
|
||||
parser/
|
||||
|
||||
|
||||
envs.sh
|
47
README.md
47
README.md
@ -1,4 +1,4 @@
|
||||
## Start aplikacji
|
||||
# Start aplikacji
|
||||
|
||||
Zeby wystartowac aplikacje backendu najpierw nalezy postawic testowa baze danych na naszym komputerze za pomoca dockera. Jesli raz juz go odpalimy przy nastepnym razem bardzo mozliwe, ze wlaczy sie sam. AAby sprawdzic czy docker jesty wystartowany mozna uzyc `docker ps`
|
||||
|
||||
@ -13,7 +13,7 @@ cd restservice
|
||||
mvn spring-boot:run
|
||||
```
|
||||
|
||||
## Token obtaining
|
||||
# Token obtaining
|
||||
|
||||
Żeby tesotwać API wpełni potrzebny nam jest token który otrzymujemy na podstawie ticketa z systemu autoryzacyjnego **CAS**. Z tego powodu system autoryzacji działa inaczej niż w "książkowych" restowych aplikacjach i np Postman za nas jej nie dokona. Musimy mu podać już uzyskany token. Aby łatwo go uzyskać odpal skrypt
|
||||
|
||||
@ -23,7 +23,7 @@ python gettoken.py
|
||||
|
||||
Na koniec w przęglądarce dostaniesz w odpowiedzi token. W samym pliku można zmienić porty aplikacji jeśli to potrzebne.
|
||||
|
||||
## Profiles
|
||||
# Profiles
|
||||
|
||||
W aplikacji posiadamy dwa profile. `dev` i `prod`. **Dev** używamy do testowania aplikacji lokalnie. **Pord** służy do stworzenia builda na produkcję.
|
||||
Profil wybieramy w pliku `restservice/src/main/resources/application.properties` wpisując odpowiednią nazwę
|
||||
@ -45,8 +45,12 @@ W paczce dla proda w protpertiesach poufne dane odczytywane są ze zmiennych śr
|
||||
- `PLANNAPLAN_EMAIL_USERNAME` - login naszego maila
|
||||
- `PLANNAPLAN_EMAIL_PASSWORD` - hasło naszego maila
|
||||
- `PLANNAPLAN_EMAIL` - nasz adres maila
|
||||
- `PLANNAPLAN_CONSUMER_KEY` - nasz klucz do usos api
|
||||
- `PLANNAPLAN_CONSUMER_SECRET` - secret naszego klucza
|
||||
|
||||
## Packaging
|
||||
Należy też pamiętać, że zmienne `PLANNAPLAN_CONSUMER_KEY` oraz `PLANNAPLAN_CONSUMER_SECRET` są potrzebne również w profilu `dev` więc trzeba je dodać w celu tesotowania do zmiennych we własnym systemie
|
||||
|
||||
# Packaging
|
||||
|
||||
Zeby spakowac apke do `jara` wystarcza dwie komendy zaczynajac z glownego katalogu projektu
|
||||
|
||||
@ -56,23 +60,23 @@ mvn clean; mvn install; cd restservice; mvn clean package spring-boot:repackage
|
||||
|
||||
Utworzony zostanie jar w `restservice/target/restservice-1.0-SNAPSHOT.jar`. Oczywiscie zeby jar zadzialal kontenery dockerowe musza byc odpalone (lub baza danych na serwerze jesli zmienialismy propertisy z localhost)
|
||||
|
||||
## Generowanie dokumentacji
|
||||
# Generowanie dokumentacji
|
||||
|
||||
### Javadocs
|
||||
## Javadocs
|
||||
|
||||
```bash
|
||||
mvn javadoc:javadoc
|
||||
```
|
||||
|
||||
### Api docs
|
||||
## Api docs
|
||||
|
||||
Żeby zobaczyć dokumentację api trzeba wejść w przeglądarce na `http://localhost:1285/swagger-ui.html` po odpaleniu aplikacji.
|
||||
|
||||
#### Nazewnictwo odpowiedzi
|
||||
### Nazewnictwo odpowiedzi
|
||||
|
||||
Każdą odpowiedź zaczynamy od modelu, który opisuje np. `Courses` a kończymy na `Response`. Między tymi dwoma członami możemy dodawać modyfikatory opisujące dokładniej odpowiedź np. `Default`. W ten sposób możemy otrzymać nazwę `CoursesDefaultResponse.java`
|
||||
|
||||
## Troubleshooting
|
||||
# Troubleshooting
|
||||
|
||||
Spring chyba cacheuje jakies dane dotyczace polaczenia wiec jesli spring wywali Ci blad `Connection Refused`, a wiesz, ze ta baza stoi na podanym ip i porcie to sprobuj
|
||||
|
||||
@ -80,3 +84,28 @@ Spring chyba cacheuje jakies dane dotyczace polaczenia wiec jesli spring wywali
|
||||
mvn clean
|
||||
mvn install
|
||||
```
|
||||
|
||||
Jeżeli używasz VSCode i testy, które wymagają podanych zmiennych środowiskowych (testy odpytywania usos api) trzeba podać te zmienne w pliku `.vscode/settings.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"files.exclude": {
|
||||
"**/.classpath": true,
|
||||
"**/.project": true,
|
||||
"**/.settings": true,
|
||||
"**/.factorypath": true
|
||||
},
|
||||
"java.configuration.updateBuildConfiguration": "disabled",
|
||||
"java.format.settings.url": "eclipse-formatter.xml",
|
||||
"java.test.config": [
|
||||
{
|
||||
"name": "myConfiguration",
|
||||
"workingDirectory": "${workspaceFolder}",
|
||||
"env": {
|
||||
"PLANNAPLAN_CONSUMER_KEY": "value",
|
||||
"PLANNAPLAN_CONSUMER_SECRET": "value"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
@ -75,28 +75,11 @@
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.springframework.social/spring-social-core -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.social</groupId>
|
||||
<artifactId>spring-social-core</artifactId>
|
||||
<version>1.1.6.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.social</groupId>
|
||||
<artifactId>spring-social-web</artifactId>
|
||||
<version>1.1.6.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.social</groupId>
|
||||
<artifactId>spring-social-config</artifactId>
|
||||
<version>1.1.6.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.social</groupId>
|
||||
<artifactId>spring-social-security</artifactId>
|
||||
<version>1.1.6.RELEASE</version>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@ -104,6 +87,17 @@
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.scribejava</groupId>
|
||||
<artifactId>scribejava-core</artifactId>
|
||||
<version>8.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.9.8</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
@ -4,6 +4,21 @@
|
||||
"name": "plannaplan.email",
|
||||
"type": "java.lang.String",
|
||||
"description": "Email from which app sends message"
|
||||
},
|
||||
{
|
||||
"name": "plannaplan.apiurl",
|
||||
"type": "java.lang.String",
|
||||
"description": "Url to usos api endpoints"
|
||||
},
|
||||
{
|
||||
"name": "plannaplan.apikey",
|
||||
"type": "java.lang.String",
|
||||
"description": "Api consumer key"
|
||||
},
|
||||
{
|
||||
"name": "plannaplan.apisecret",
|
||||
"type": "java.lang.String",
|
||||
"description": "Api consumer secret"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
52
buisnesslogic/src/main/java/com/plannaplan/api/UsosOauth1Service.java
Executable file
52
buisnesslogic/src/main/java/com/plannaplan/api/UsosOauth1Service.java
Executable file
@ -0,0 +1,52 @@
|
||||
package com.plannaplan.api;
|
||||
|
||||
import com.github.scribejava.core.builder.api.DefaultApi10a;
|
||||
|
||||
public class UsosOauth1Service extends DefaultApi10a {
|
||||
|
||||
private static final String AUTHORIZE_URL = "https://usosapidemo.amu.edu.pl/services/oauth/authorize";
|
||||
private static final String REQUEST_TOKEN_URL = "https://usosapidemo.amu.edu.pl/services/oauth/request_token";
|
||||
|
||||
private final String scopesAsString;
|
||||
|
||||
protected UsosOauth1Service() {
|
||||
scopesAsString = null;
|
||||
}
|
||||
|
||||
protected UsosOauth1Service(String... scopes) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (String scope : scopes) {
|
||||
builder.append('+').append(scope);
|
||||
}
|
||||
scopesAsString = "?scope=" + builder.substring(1);
|
||||
}
|
||||
|
||||
private static class InstanceHolder {
|
||||
|
||||
private static final UsosOauth1Service INSTANCE = new UsosOauth1Service();
|
||||
}
|
||||
|
||||
public static UsosOauth1Service instance() {
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
public static UsosOauth1Service instance(String... scopes) {
|
||||
return scopes == null || scopes.length == 0 ? instance() : new UsosOauth1Service(scopes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint() {
|
||||
return scopesAsString == null ? REQUEST_TOKEN_URL : REQUEST_TOKEN_URL + scopesAsString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint() {
|
||||
return "https://usosapidemo.amu.edu.pl/services/oauth/access_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAuthorizationBaseUrl() {
|
||||
return AUTHORIZE_URL;
|
||||
}
|
||||
|
||||
}
|
29
buisnesslogic/src/main/java/com/plannaplan/models/UserApiResponse.java
Executable file
29
buisnesslogic/src/main/java/com/plannaplan/models/UserApiResponse.java
Executable file
@ -0,0 +1,29 @@
|
||||
package com.plannaplan.models;
|
||||
|
||||
/**
|
||||
* Model to keep data from /services/users/user response called in
|
||||
* UsosApiService
|
||||
*/
|
||||
public class UserApiResponse {
|
||||
private String name;
|
||||
private String surname;
|
||||
|
||||
public UserApiResponse() {
|
||||
}
|
||||
|
||||
public String getSurname() {
|
||||
return surname;
|
||||
}
|
||||
|
||||
public void setSurname(String surname) {
|
||||
this.surname = surname;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
@ -1,54 +1,74 @@
|
||||
package com.plannaplan.services;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.social.oauth1.OAuth1Parameters;
|
||||
import org.springframework.social.support.ClientHttpRequestFactorySelector;
|
||||
// import org.springframework.social.oauth1.OAuth1Template;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import com.github.scribejava.core.builder.ServiceBuilder;
|
||||
import com.github.scribejava.core.model.OAuth1AccessToken;
|
||||
import com.github.scribejava.core.model.OAuthRequest;
|
||||
import com.github.scribejava.core.model.Response;
|
||||
import com.github.scribejava.core.model.Verb;
|
||||
import com.github.scribejava.core.oauth.OAuth10aService;
|
||||
import com.plannaplan.api.UsosOauth1Service;
|
||||
import com.plannaplan.models.UserApiResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.social.oauth1.*;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
// import org.springframework.social.oauth1.ProtectedResourceClientFactory;
|
||||
|
||||
@Service
|
||||
/**
|
||||
* service to call usos api endpoints
|
||||
*/
|
||||
public class UsosApiService {
|
||||
|
||||
private static final String NAME_FIELD = "first_name";
|
||||
private static final String SURNAME_FIELD = "last_name";
|
||||
|
||||
@Value("${plannaplan.apiurl}")
|
||||
private String apiUrl;
|
||||
|
||||
@Value("${plannaplan.apikey}")
|
||||
private String apikey;
|
||||
|
||||
@Value("${plannaplan.apisecret}")
|
||||
private String apisecret;
|
||||
|
||||
public UsosApiService() {
|
||||
|
||||
}
|
||||
|
||||
public void xd() {
|
||||
RestTemplate xddd = new RestTemplate();
|
||||
/**
|
||||
* /services/users/user
|
||||
*
|
||||
* @param usosId user id in usos
|
||||
* @return UserApiResponse modle contatining desired values
|
||||
*/
|
||||
public UserApiResponse getUserData(String usosId) {
|
||||
final UserApiResponse apiResponse = new UserApiResponse();
|
||||
try {
|
||||
final OAuth10aService service = new ServiceBuilder(apikey).apiSecret(apisecret)
|
||||
.build(UsosOauth1Service.instance());
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("oauth_version", "1.0");
|
||||
headers.set("oauth_signature_method", "HMAC-SHA1");
|
||||
headers.set("oauth_consumer_key", "e6jbeN57HC99MfsfmZwN");
|
||||
headers.set("oauth_signature", "fhcLdwerJyzZBGA9WnAYzbySJRW9Wv5wj3h8uVgp");
|
||||
headers.set("oauth_nonce", "" + (int) (Math.random() * 100000000));
|
||||
headers.set("oauth_timestamp", "" + (System.currentTimeMillis() / 1000));
|
||||
final OAuthRequest request = new OAuthRequest(Verb.GET, apiUrl + "/services/users/user?user_id=" + usosId);
|
||||
service.signRequest(new OAuth1AccessToken("", ""), request);
|
||||
|
||||
// BasicAuthenticationInterceptor
|
||||
try (Response response = service.execute(request)) {
|
||||
final String json = response.getBody();
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
Map<String, String> map = mapper.readValue(json, new TypeReference<Map<String, String>>() {
|
||||
});
|
||||
apiResponse.setName(map.get(NAME_FIELD));
|
||||
apiResponse.setSurname(map.get(SURNAME_FIELD));
|
||||
}
|
||||
} catch (IOException | InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// OAuth1Credentials credentials;
|
||||
// RestTemplate client = new
|
||||
// RestTemplate(ClientHttpRequestFactorySelector.getRequestFactory());
|
||||
// OAuth1RequestInterceptor interceptor = new
|
||||
// OAuth1RequestInterceptor(credentials);
|
||||
// List<ClientHttpRequestInterceptor> interceptors = new
|
||||
// LinkedList<ClientHttpRequestInterceptor>();
|
||||
// interceptors.add(interceptor);
|
||||
// client.setInterceptors(interceptors);
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(headers);
|
||||
|
||||
ResponseEntity<String> result = xddd.exchange("https://usosapidemo.amu.edu.pl/services/users/user",
|
||||
HttpMethod.GET, entity, String.class);
|
||||
System.out.println(result);
|
||||
return apiResponse;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,36 +2,37 @@ package com.plannaplan.services;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.annotation.DirtiesContext.MethodMode;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.plannaplan.entities.User;
|
||||
import com.plannaplan.exceptions.UserNotFoundException;
|
||||
import com.plannaplan.types.UserRoles;
|
||||
import com.plannaplan.models.UserApiResponse;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@ContextConfiguration
|
||||
@TestMethodOrder(OrderAnnotation.class)
|
||||
public class UsosApiServiceTest {
|
||||
|
||||
@Autowired
|
||||
private UsosApiService service;
|
||||
|
||||
@Test
|
||||
public void chuj() {
|
||||
this.service.xd();
|
||||
@Ignore
|
||||
public void shouldReturnPersonalData() throws IOException, InterruptedException, ExecutionException {
|
||||
|
||||
final UserApiResponse response = this.service.getUserData("499054");
|
||||
|
||||
assertTrue(response.getName().equals("Marcin"));
|
||||
assertTrue(response.getSurname().equals("Woźniak"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,5 +14,8 @@ spring.mail.properties.mail.smtp.auth=false
|
||||
spring.mail.properties.mail.smtp.starttls.enable=false
|
||||
|
||||
plannaplan.email = plannaplan.kontakt@gmail.com
|
||||
plannaplan.apiurl = https://usosapidemo.amu.edu.pl
|
||||
plannaplan.apikey=${PLANNAPLAN_CONSUMER_KEY}
|
||||
plannaplan.apisecret=${PLANNAPLAN_CONSUMER_SECRET}
|
||||
|
||||
server.port=1285
|
@ -18,4 +18,7 @@ logging.level.io.swagger.models.parameters.AbstractSerializableParameter=ERROR
|
||||
server.port=1285
|
||||
plannaplan.dev = true
|
||||
plannaplan.frontendUrl = http://localhost:3000
|
||||
plannaplan.email = plannaplan.kontakt@gmail.com
|
||||
plannaplan.email = plannaplan.kontakt@gmail.com
|
||||
plannaplan.apiurl = https://usosapidemo.amu.edu.pl
|
||||
plannaplan.apikey=${PLANNAPLAN_CONSUMER_KEY}
|
||||
plannaplan.apisecret=${PLANNAPLAN_CONSUMER_SECRET}
|
@ -20,6 +20,10 @@ server.port=1285
|
||||
plannaplan.email = ${PLANNAPLAN_EMAIL}
|
||||
plannaplan.dev = false
|
||||
plannaplan.frontendUrl= https://wmi.plannaplan.pl
|
||||
plannaplan.apiurl = https://usosapidemo.amu.edu.pl
|
||||
plannaplan.apikey=${PLANNAPLAN_CONSUMER_KEY}
|
||||
plannaplan.apisecret=${PLANNAPLAN_CONSUMER_SECRET}
|
||||
|
||||
security.require-ssl=true
|
||||
server.ssl.key-store=/keys/keystore.p12
|
||||
server.ssl.key-store-password=
|
||||
|
Loading…
Reference in New Issue
Block a user