UNCLASSIFIED
Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
TRON
A
Arcade-Archive
tron-common-api
tron-common-api
Compare Revisions
34632cf58bfecc1fedde0999da1bd743daa53e7b...3e088f2203805f593bea529579819337dd84dfc6
Commits (4)
carved out cruft not needed outside of tron proper
· 382a7202
Christopher Zell
authored
Aug 24, 2021
382a7202
squashed migration files
· e47216ba
Christopher Zell
authored
Aug 24, 2021
e47216ba
more trimming
· c9bca81e
Christopher Zell
authored
Aug 24, 2021
c9bca81e
helper launch script
· 3e088f22
Christopher Zell
authored
Aug 24, 2021
3e088f22
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
9 additions
and
816 deletions
+9
-816
diffdb.sh
diffdb.sh
+3
-0
pom.xml
pom.xml
+0
-37
prod.sh
prod.sh
+6
-3
src/main/java/mil/tron/commonapi/ApplicationProperties.java
src/main/java/mil/tron/commonapi/ApplicationProperties.java
+0
-49
src/main/java/mil/tron/commonapi/CacheConfig.java
src/main/java/mil/tron/commonapi/CacheConfig.java
+0
-66
src/main/java/mil/tron/commonapi/CommonApiApplication.java
src/main/java/mil/tron/commonapi/CommonApiApplication.java
+0
-38
src/main/java/mil/tron/commonapi/CustomMeterRegistry.java
src/main/java/mil/tron/commonapi/CustomMeterRegistry.java
+0
-52
src/main/java/mil/tron/commonapi/CustomRegistryConfig.java
src/main/java/mil/tron/commonapi/CustomRegistryConfig.java
+0
-13
src/main/java/mil/tron/commonapi/MetricsConfig.java
src/main/java/mil/tron/commonapi/MetricsConfig.java
+0
-48
src/main/java/mil/tron/commonapi/SpringdocConfig.java
src/main/java/mil/tron/commonapi/SpringdocConfig.java
+0
-16
src/main/java/mil/tron/commonapi/annotation/efa/ProtectedField.java
...ava/mil/tron/commonapi/annotation/efa/ProtectedField.java
+0
-12
src/main/java/mil/tron/commonapi/annotation/pubsub/PreAuthorizeAnyAppClientOrDeveloper.java
...nnotation/pubsub/PreAuthorizeAnyAppClientOrDeveloper.java
+0
-18
src/main/java/mil/tron/commonapi/annotation/pubsub/PreAuthorizeSubscriptionCreation.java
...i/annotation/pubsub/PreAuthorizeSubscriptionCreation.java
+0
-37
src/main/java/mil/tron/commonapi/annotation/pubsub/PreAuthorizeSubscriptionOwner.java
...napi/annotation/pubsub/PreAuthorizeSubscriptionOwner.java
+0
-31
src/main/java/mil/tron/commonapi/annotation/security/PreAuthorizeGateway.java
...on/commonapi/annotation/security/PreAuthorizeGateway.java
+0
-12
src/main/java/mil/tron/commonapi/appgateway/AppGatewayRouteBuilder.java
...mil/tron/commonapi/appgateway/AppGatewayRouteBuilder.java
+0
-38
src/main/java/mil/tron/commonapi/appgateway/AppSourceConfig.java
...n/java/mil/tron/commonapi/appgateway/AppSourceConfig.java
+0
-123
src/main/java/mil/tron/commonapi/appgateway/AppSourceEndpoint.java
...java/mil/tron/commonapi/appgateway/AppSourceEndpoint.java
+0
-11
src/main/java/mil/tron/commonapi/appgateway/AppSourceEndpointsBuilder.java
.../tron/commonapi/appgateway/AppSourceEndpointsBuilder.java
+0
-197
src/main/java/mil/tron/commonapi/appgateway/AppSourceInterfaceDefinition.java
...on/commonapi/appgateway/AppSourceInterfaceDefinition.java
+0
-15
No files found.
diffdb.sh
0 → 100755
View file @
3e088f22
#! bash
mvn
-Dliquibase
.url
=
jdbc:postgresql://localhost:5432/common_slim
-Dliquibase
.username
=
${
USER
}
-Dliquibase
.password
=
''
-Pproduction
liquibase:diff
pom.xml
View file @
3e088f22
...
...
@@ -68,10 +68,6 @@
<artifactId>
spring-boot-starter-aop
</artifactId>
<version>
2.5.2
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-cache
</artifactId>
</dependency>
<dependency>
<groupId>
com.fasterxml.jackson.dataformat
</groupId>
<artifactId>
jackson-dataformat-yaml
</artifactId>
...
...
@@ -159,23 +155,6 @@
<artifactId>
json-patch
</artifactId>
<version>
1.12
</version>
</dependency>
<dependency>
<groupId>
org.apache.camel
</groupId>
<artifactId>
camel-core
</artifactId>
<version>
${camel.version}
</version>
<type>
test-jar
</type>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.apache.camel
</groupId>
<artifactId>
camel-test-spring
</artifactId>
<version>
${camel.version}
</version>
</dependency>
<dependency>
<groupId>
org.apache.camel
</groupId>
<artifactId>
camel-test
</artifactId>
<version>
${camel.version}
</version>
</dependency>
<dependency>
<groupId>
com.jayway.jsonpath
</groupId>
<artifactId>
json-path
</artifactId>
...
...
@@ -191,22 +170,6 @@
<artifactId>
camel-spring-boot-starter
</artifactId>
<version>
${camel.version}
</version>
</dependency>
<dependency>
<groupId>
org.apache.camel
</groupId>
<artifactId>
camel-jackson
</artifactId>
<version>
${camel.version}
</version>
</dependency>
<dependency>
<groupId>
org.apache.camel
</groupId>
<artifactId>
camel-servlet
</artifactId>
<version>
${camel.version}
</version>
</dependency>
<dependency>
<groupId>
org.apache.camel
</groupId>
<artifactId>
camel-http
</artifactId>
<version>
${camel.version}
</version>
</dependency>
<dependency>
<groupId>
org.springdoc
</groupId>
<artifactId>
springdoc-openapi-data-rest
</artifactId>
...
...
prod.sh
View file @
3e088f22
export
DB_NAME
=
'common_slim'
createdb
${
DB_NAME
}
if
[[
"
$1
"
==
"clean"
]]
;
then
echo
"Cleaning and re-creating db..."
;
dropdb
common
;
createdb
common
;
dropdb
${
DB_NAME
}
;
createdb
${
DB_NAME
}
;
fi
;
export
SPRING_PROFILES_ACTIVE
=
production
;
export
SECURITY_ENABLED
=
true
;
export
PGHOST
=
'localhost'
;
export
PGPORT
=
'5432'
;
export
PG_DATABASE
=
common
;
export
PG_DATABASE
=
${
DB_NAME
}
;
export
APP_DB_ADMIN_PASSWORD
=
''
;
export
PG_USER
=
${
USER
}
;
export
APP_DB_RW_PASSWORD
=
''
;
...
...
src/main/java/mil/tron/commonapi/ApplicationProperties.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
import
javax.annotation.PostConstruct
;
import
javax.validation.constraints.NotEmpty
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.validation.annotation.Validated
;
import
lombok.Getter
;
import
lombok.Setter
;
@Configuration
@ConfigurationProperties
()
@Validated
public
class
ApplicationProperties
{
@Getter
@Setter
private
List
<
String
>
combinedPrefixes
=
new
ArrayList
<>();
@Getter
@Setter
@NotEmpty
private
Map
<
String
,
@NotEmpty
String
>
apiPrefix
;
@Getter
@Setter
@NotEmpty
private
String
appSourcesPrefix
;
@PostConstruct
private
void
createCombinedPrefixes
()
{
if
(
apiPrefix
!=
null
&&
!
apiPrefix
.
isEmpty
())
{
String
appSourcePath
=
appSourcesPrefix
==
null
?
""
:
appSourcesPrefix
;
this
.
combinedPrefixes
.
addAll
(
apiPrefix
.
values
().
stream
().
map
(
prefix
->
{
if
(
prefix
!=
null
)
{
return
prefix
.
concat
(
appSourcePath
);
}
return
appSourcePath
;
}).
collect
(
Collectors
.
toList
()));
}
}
}
src/main/java/mil/tron/commonapi/CacheConfig.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi
;
import
java.util.concurrent.TimeUnit
;
import
com.github.benmanes.caffeine.cache.Caffeine
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.cache.CacheManager
;
import
org.springframework.cache.annotation.EnableCaching
;
import
org.springframework.cache.caffeine.CaffeineCacheManager
;
import
org.springframework.cache.concurrent.ConcurrentMapCacheManager
;
import
org.springframework.cache.interceptor.CacheResolver
;
import
org.springframework.cache.interceptor.KeyGenerator
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Primary
;
import
org.springframework.context.annotation.PropertySource
;
import
mil.tron.commonapi.appgateway.GatewayCacheResolver
;
import
mil.tron.commonapi.appgateway.GatewayKeyGenerator
;
@Configuration
@EnableCaching
(
order
=
2147483647
)
@ConditionalOnProperty
(
name
=
"caching.enabled"
)
@PropertySource
(
"classpath:application.properties"
)
public
class
CacheConfig
{
public
static
final
String
SERVICE_ENTITY_CACHE_MANAGER
=
"serviceEntityCacheManager"
;
public
static
final
String
APP_SOURCE_DETAILS_CACHE_NAME
=
"app_source_details_cache"
;
@Bean
public
Caffeine
<
Object
,
Object
>
caffeineConfig
(
@Value
(
"${caching.expire.time:10}"
)
int
expireTime
,
@Value
(
"${caching.expire.unit:MINUTES}"
)
String
expireUnit
)
{
TimeUnit
unit
;
try
{
unit
=
TimeUnit
.
valueOf
(
expireUnit
);
}
catch
(
IllegalArgumentException
iaEx
)
{
unit
=
TimeUnit
.
MINUTES
;
}
return
Caffeine
.
newBuilder
().
expireAfterWrite
(
expireTime
,
unit
);
}
@Primary
@Bean
public
CacheManager
cacheManager
(
Caffeine
<
Object
,
Object
>
caffeine
)
{
CaffeineCacheManager
caffeineCacheManager
=
new
CaffeineCacheManager
();
caffeineCacheManager
.
setCaffeine
(
caffeine
);
return
caffeineCacheManager
;
}
@Bean
public
CacheManager
serviceEntityCacheManager
()
{
return
new
ConcurrentMapCacheManager
(
APP_SOURCE_DETAILS_CACHE_NAME
);
}
@Bean
(
"gatewayCacheResolver"
)
public
CacheResolver
cacheResolver
()
{
return
new
GatewayCacheResolver
();
}
@Bean
(
"gatewayKeyGenerator"
)
public
KeyGenerator
keyGenerator
()
{
return
new
GatewayKeyGenerator
();
}
}
src/main/java/mil/tron/commonapi/CommonApiApplication.java
View file @
3e088f22
package
mil.tron.commonapi
;
import
mil.tron.commonapi.entity.appsource.AppSource
;
import
mil.tron.commonapi.repository.appsource.AppSourceRepository
;
import
mil.tron.commonapi.service.AppSourceService
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.ApplicationRunner
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.web.client.RestTemplateBuilder
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.scheduling.annotation.EnableAsync
;
import
org.springframework.scheduling.annotation.EnableScheduling
;
import
org.springframework.web.client.RestTemplate
;
import
org.springframework.web.filter.CommonsRequestLoggingFilter
;
import
java.time.Duration
;
import
java.util.List
;
@SpringBootApplication
@EnableAsync
@EnableScheduling
...
...
@@ -37,32 +27,4 @@ public class CommonApiApplication {
return
loggingFilter
;
}
/**
* Publisher-Subscriber REST bean that will timeout after 5secs to a subscriber so that
* a subscriber can't block/hang the publisher thread
* @param builder
* @return RestTemplate for use by the EventPublisher
*/
@Bean
(
"eventSender"
)
public
RestTemplate
publisherSender
(
@Value
(
"${webhook-send-timeout-secs:5}"
)
long
webhookSendTimeoutSecs
,
RestTemplateBuilder
builder
)
{
return
builder
.
setConnectTimeout
(
Duration
.
ofSeconds
(
webhookSendTimeoutSecs
))
.
setReadTimeout
(
Duration
.
ofSeconds
(
webhookSendTimeoutSecs
))
.
build
();
}
/**
* Launch the health check instances for each app source that's supposed to report status
*/
@Bean
public
ApplicationRunner
init
(
AppSourceService
appSourceService
,
AppSourceRepository
appSourceRepository
)
{
return
(
args
)
->
{
List
<
AppSource
>
appSources
=
appSourceRepository
.
findAll
();
for
(
AppSource
appSource
:
appSources
)
{
appSourceService
.
registerAppReporting
(
appSource
);
}
};
}
}
src/main/java/mil/tron/commonapi/CustomMeterRegistry.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi
;
import
java.util.Date
;
import
java.util.concurrent.ThreadFactory
;
import
java.util.concurrent.TimeUnit
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
io.micrometer.core.instrument.Clock
;
import
io.micrometer.core.instrument.step.StepMeterRegistry
;
import
io.micrometer.core.instrument.util.MeterPartition
;
import
io.micrometer.core.instrument.util.NamedThreadFactory
;
import
mil.tron.commonapi.service.MetricService
;
public
class
CustomMeterRegistry
extends
StepMeterRegistry
{
private
static
final
ThreadFactory
DEFAULT_THREAD_FACTORY
=
new
NamedThreadFactory
(
"gateway-metrics-publisher"
);
private
CustomRegistryConfig
config
;
private
MetricService
metricService
;
public
CustomMeterRegistry
(
CustomRegistryConfig
config
,
Clock
clock
,
MetricService
metricService
)
{
this
(
config
,
clock
,
DEFAULT_THREAD_FACTORY
,
metricService
);
}
@Autowired
public
CustomMeterRegistry
(
CustomRegistryConfig
config
,
Clock
clock
,
ThreadFactory
threadFactory
,
MetricService
metricService
)
{
super
(
config
,
clock
);
this
.
config
=
config
;
this
.
metricService
=
metricService
;
start
(
threadFactory
);
}
@Override
public
void
start
(
ThreadFactory
threadFactory
)
{
super
.
start
(
threadFactory
);
}
public
CustomRegistryConfig
getConfig
()
{
return
config
;
}
@Override
protected
void
publish
()
{
// partition into smaller chunks, because we might have a lot of stuff....
this
.
metricService
.
publishToDatabase
(
MeterPartition
.
partition
(
this
,
config
.
batchSize
()),
new
Date
(),
this
);
}
@Override
protected
TimeUnit
getBaseTimeUnit
()
{
return
TimeUnit
.
MILLISECONDS
;
}
}
\ No newline at end of file
src/main/java/mil/tron/commonapi/CustomRegistryConfig.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi
;
import
io.micrometer.core.instrument.step.StepRegistryConfig
;
public
interface
CustomRegistryConfig
extends
StepRegistryConfig
{
CustomRegistryConfig
DEFAULT
=
k
->
null
;
@Override
default
String
prefix
()
{
return
"gateway"
;
}
}
\ No newline at end of file
src/main/java/mil/tron/commonapi/MetricsConfig.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi
;
import
java.time.Duration
;
import
java.util.Arrays
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.PropertySource
;
import
io.micrometer.core.instrument.Clock
;
import
io.micrometer.core.instrument.composite.CompositeMeterRegistry
;
import
io.micrometer.core.instrument.config.MeterFilter
;
import
mil.tron.commonapi.service.MetricService
;
@Configuration
@ConditionalOnProperty
(
name
=
"metrics.save.enabled"
)
@PropertySource
(
"classpath:application.properties"
)
public
class
MetricsConfig
{
@Bean
()
public
CustomRegistryConfig
customRegistryConfig
(
@Value
(
"${metrics.stepsize:10}"
)
int
stepsize
)
{
return
new
CustomRegistryConfig
(){
@Override
public
Duration
step
()
{
return
Duration
.
ofMinutes
(
stepsize
);
}
@Override
public
String
get
(
String
key
)
{
return
null
;
}
};
}
@Bean
()
public
CompositeMeterRegistry
compositeMeterRegistry
(
MetricService
metricService
,
CustomRegistryConfig
customRegistryConfig
)
{
return
new
CompositeMeterRegistry
(
Clock
.
SYSTEM
,
Arrays
.
asList
(
new
CustomMeterRegistry
(
customRegistryConfig
,
Clock
.
SYSTEM
,
metricService
)
));
}
@Bean
public
MeterFilter
meterFilter
()
{
return
MeterFilter
.
denyUnless
((
id
)
->
id
.
getName
().
startsWith
(
"gateway"
));
}
}
\ No newline at end of file
src/main/java/mil/tron/commonapi/SpringdocConfig.java
View file @
3e088f22
...
...
@@ -24,14 +24,7 @@ public class SpringdocConfig {
String
[]
paths
=
{
String
.
format
(
"%s/person/**"
,
apiPrefix
),
String
.
format
(
"%s/organization/**"
,
apiPrefix
),
String
.
format
(
"%s/airman/**"
,
apiPrefix
),
String
.
format
(
"%s/subscriptions/**"
,
apiPrefix
),
String
.
format
(
"%s/flight/**"
,
apiPrefix
),
String
.
format
(
"%s/group/**"
,
apiPrefix
),
String
.
format
(
"%s/squadron/**"
,
apiPrefix
),
String
.
format
(
"%s/wing/**"
,
apiPrefix
),
String
.
format
(
"%s/userinfo/**"
,
apiPrefix
),
String
.
format
(
"%s/scratch/**"
,
apiPrefix
),
String
.
format
(
"%s/version/**"
,
apiPrefix
),
};
...
...
@@ -41,12 +34,10 @@ public class SpringdocConfig {
@Bean
public
GroupedOpenApi
dashboardApi
(
@Value
(
"${api-prefix.v1}"
)
String
apiPrefix
)
{
String
[]
paths
=
{
String
.
format
(
"%s/app-client/**"
,
apiPrefix
),
String
.
format
(
"%s/privilege/**"
,
apiPrefix
),
String
.
format
(
"%s/logfile/**"
,
apiPrefix
),
String
.
format
(
"%s/logs/**"
,
apiPrefix
),
String
.
format
(
"%s/dashboard-users/**"
,
apiPrefix
),
String
.
format
(
"%s/app-source/**"
,
apiPrefix
),
};
return
GroupedOpenApi
.
builder
().
group
(
"dashboard-api"
).
pathsToMatch
(
paths
).
build
();
}
...
...
@@ -56,14 +47,7 @@ public class SpringdocConfig {
String
[]
paths
=
{
String
.
format
(
"%s/person/**"
,
apiPrefix
),
String
.
format
(
"%s/organization/**"
,
apiPrefix
),
String
.
format
(
"%s/airman/**"
,
apiPrefix
),
String
.
format
(
"%s/subscriptions/**"
,
apiPrefix
),
String
.
format
(
"%s/flight/**"
,
apiPrefix
),
String
.
format
(
"%s/group/**"
,
apiPrefix
),
String
.
format
(
"%s/squadron/**"
,
apiPrefix
),
String
.
format
(
"%s/wing/**"
,
apiPrefix
),
String
.
format
(
"%s/userinfo/**"
,
apiPrefix
),
String
.
format
(
"%s/scratch/**"
,
apiPrefix
),
};
return
GroupedOpenApi
.
builder
().
group
(
"common-api-v2"
).
pathsToMatch
(
paths
).
build
();
...
...
src/main/java/mil/tron/commonapi/annotation/efa/ProtectedField.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.annotation.efa
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
/**
* Simple annotation to mark a field for the ValidateEntityAccess class
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
ProtectedField
{
}
src/main/java/mil/tron/commonapi/annotation/pubsub/PreAuthorizeAnyAppClientOrDeveloper.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.annotation.pubsub
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
/**
* Preauthorizes access to pub sub ledger/replay/event endpoints if requester is a:
* - APP_CLIENT_DEVELOPER of any app, or
* - any APP_CLIENT, or
* - a DASHBOARD_ADMIN
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
@PreAuthorize
(
"hasAuthority('APP_CLIENT_DEVELOPER') || hasAuthority('APP_CLIENT') || hasAuthority('DASHBOARD_ADMIN')"
)
public
@interface
PreAuthorizeAnyAppClientOrDeveloper
{
}
src/main/java/mil/tron/commonapi/annotation/pubsub/PreAuthorizeSubscriptionCreation.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.annotation.pubsub
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
org.springframework.security.access.prepost.PreAuthorize
;
/**
* Authorizes new subscription if the request is from a:
* - DASHBOARD_ADMIN, or
* - Requesting entity is a registered APP_CLIENT itself, or
* - Requesting entity is an APP_CLIENT_DEVELOPER of a registered app client
*
* Authorizes update of an EXISTING subscription if the request is from a:
* - DASHBOARD_ADMIN, or
* - Requesting entity is a registered APP_CLIENT_DEVELOPER of the registered app client for whom the subscription exists, or
* -
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
@PreAuthorize
(
// first see if the subscription even exists
"(@subscriberServiceImpl.subscriptionExists(#subscriber.getId()) ? "
+
// if it does then authorize if req is from app client dev associated with subscription or
// req is from the app client itself (namespace in subscribers URI equals user (app) in request principal)
"@appClientUserServiceImpl.userIsAppClientDeveloperForAppSubscription(#subscriber.getId(), authentication.getName()) : "
+
// otherwise, if subscription is new, then any APP_CLIENT or APP_CLIENT_DEVELOPER is permitted
"(hasAuthority('APP_CLIENT') || hasAuthority('APP_CLIENT_DEVELOPER'))) "
+
// if we get here, then DASHBOARD_ADMIN always trumps all
"|| hasAuthority('DASHBOARD_ADMIN')"
)
public
@interface
PreAuthorizeSubscriptionCreation
{
}
src/main/java/mil/tron/commonapi/annotation/pubsub/PreAuthorizeSubscriptionOwner.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.annotation.pubsub
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
/**
* Authorizes subscription retrieval/removal/etc if the requester is from a:
* - DASHBOARD_ADMIN, or
* - Requesting entity is a registered APP_CLIENT itself associated with given 'id' from the controller, or
* - Requesting entity is an APP_CLIENT_DEVELOPER of a registered app client for whom the subscription of 'id' is for
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
@PreAuthorize
(
// first see if the subscription even exists
"(@subscriberServiceImpl.subscriptionExists(#id) ? "
+
// if it does then authorize if req is from app client dev associated with subscription or
// req is from the app client itself (namespace in subscribers URI equals user (app) in request principal)
"@appClientUserServiceImpl.userIsAppClientDeveloperForAppSubscription(#id, authentication.getName()) : "
+
// otherwise, if subscription does not exist, then deny
"false )"
+
// if we get here, then DASHBOARD_ADMIN always trumps all
"|| hasAuthority('DASHBOARD_ADMIN')"
)
public
@interface
PreAuthorizeSubscriptionOwner
{
}
src/main/java/mil/tron/commonapi/annotation/security/PreAuthorizeGateway.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.annotation.security
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
org.springframework.security.access.prepost.PreAuthorize
;
@Retention
(
RetentionPolicy
.
RUNTIME
)
@PreAuthorize
(
"hasAuthority('DASHBOARD_ADMIN') || @accessCheck.check(#requestObject)"
)
public
@interface
PreAuthorizeGateway
{
}
src/main/java/mil/tron/commonapi/appgateway/AppGatewayRouteBuilder.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.appgateway
;
import
org.apache.camel.CamelContext
;
import
org.springframework.stereotype.Service
;
import
lombok.extern.slf4j.Slf4j
;
@Slf4j
@Service
public
class
AppGatewayRouteBuilder
{
public
static
final
String
ROUTE_TYPE
=
"direct:"
;
public
static
final
String
APP_GATEWAY_ENDPOINT_ID
=
"app-gateway"
;
private
CamelContext
camelContext
;
public
AppGatewayRouteBuilder
(
CamelContext
camelContext
)
{
this
.
camelContext
=
camelContext
;
}
public
GatewayRoute
createGatewayRoute
(
String
appSourcePath
)
{
final
GatewayRoute
route
=
new
GatewayRoute
(
camelContext
,
appSourcePath
);
try
{
camelContext
.
addRoutes
(
route
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"Could not create Camel route for the App Source: "
+
appSourcePath
);
}
return
route
;
}
public
static
String
generateAppSourceRouteUri
(
String
appSourcePath
)
{
return
ROUTE_TYPE
+
appSourcePath
;
}
public
static
String
generateAppSourceRouteId
(
String
appSourcePath
)
{
return
String
.
format
(
"%s_%s"
,
APP_GATEWAY_ENDPOINT_ID
,
appSourcePath
);
}
}
src/main/java/mil/tron/commonapi/appgateway/AppSourceConfig.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.appgateway
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.transaction.Transactional
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
import
lombok.extern.slf4j.Slf4j
;
import
mil.tron.commonapi.entity.appsource.AppSource
;
import
mil.tron.commonapi.repository.appsource.AppSourceRepository
;
@Service
@Slf4j
public
class
AppSourceConfig
{
private
Map
<
AppSourceInterfaceDefinition
,
AppSource
>
appSourceDefs
;
private
Map
<
String
,
AppSourceInterfaceDefinition
>
appSourcePathToDefinitionMap
;
private
AppSourceRepository
appSourceRepository
;
@Autowired
public
AppSourceConfig
(
AppSourceRepository
appSourceRepository
,
@Value
(
"${appsource.definition-file}"
)
String
appSourceDefFile
)
{
this
.
appSourceRepository
=
appSourceRepository
;
this
.
appSourceDefs
=
new
HashMap
<>();
this
.
appSourcePathToDefinitionMap
=
new
HashMap
<>();
this
.
registerAppSources
(
this
.
parseAppSourceDefs
(
appSourceDefFile
));
}
private
AppSourceInterfaceDefinition
[]
parseAppSourceDefs
(
String
configFile
)
{
ObjectMapper
objectMapper
=
new
ObjectMapper
();
AppSourceInterfaceDefinition
[]
defs
=
null
;
try
(
InputStream
in
=
getClass
().
getResourceAsStream
(
configFile
);
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
in
));
)
{
defs
=
objectMapper
.
readValue
(
reader
,
AppSourceInterfaceDefinition
[].
class
);
}
catch
(
IOException
e
)
{
log
.
warn
(
"Could not parse app source file config."
);
}
catch
(
NullPointerException
e
)
{
log
.
warn
(
"Could not find resource file."
,
e
);
}
return
defs
;
}
public
Map
<
AppSourceInterfaceDefinition
,
AppSource
>
getAppSourceDefs
()
{
return
this
.
appSourceDefs
;
}
private
void
registerAppSources
(
AppSourceInterfaceDefinition
[]
appSourceDefs
)
{
// attempt adding
if
(
appSourceDefs
!=
null
)
{
for
(
AppSourceInterfaceDefinition
appDef
:
appSourceDefs
)
{
this
.
appSourceDefs
.
put
(
appDef
,
this
.
registerAppSource
(
appDef
));
}
}
}
@Transactional
AppSource
registerAppSource
(
AppSourceInterfaceDefinition
appDef
)
{
AppSource
appSource
;
if
(!
this
.
appSourceRepository
.
existsByNameIgnoreCase
(
appDef
.
getName
()))
{
// add new app source
appSource
=
AppSource
.
builder
()
.
name
(
appDef
.
getName
())
.
openApiSpecFilename
(
appDef
.
getOpenApiSpecFilename
())
.
appSourcePath
(
appDef
.
getAppSourcePath
())
.
availableAsAppSource
(
true
)
.
nameAsLower
(
appDef
.
getName
().
toLowerCase
())
.
build
();
}
else
{
appSource
=
this
.
appSourceRepository
.
findByNameIgnoreCaseWithEndpoints
(
appDef
.
getName
());
// refresh the database to always be correct
appSource
.
setAvailableAsAppSource
(
true
);
appSource
.
setOpenApiSpecFilename
(
appDef
.
getOpenApiSpecFilename
());
appSource
.
setAppSourcePath
(
appDef
.
getAppSourcePath
());
}
try
{
this
.
appSourceRepository
.
save
(
appSource
);
}
catch
(
Exception
e
)
{
log
.
warn
(
String
.
format
(
"Unable to add app source %s."
,
appDef
.
getName
()),
e
);
}
return
this
.
appSourceRepository
.
findByNameIgnoreCaseWithEndpoints
(
appDef
.
getName
());
}
/**
* Adds a source def mapping to the map
* @param appSourcePath
* @param appDef
* @return True if the app def is added. False if the app source path is not added and was already defined.
*/
public
boolean
addAppSourcePathToDefMapping
(
String
appSourcePath
,
AppSourceInterfaceDefinition
appDef
)
{
if
(
this
.
appSourcePathToDefinitionMap
.
get
(
appSourcePath
)
==
null
)
{
this
.
appSourcePathToDefinitionMap
.
put
(
appSourcePath
,
appDef
);
return
true
;
}
return
false
;
}
public
void
clearAppSourceDefs
()
{
this
.
appSourcePathToDefinitionMap
.
clear
();
}
public
Map
<
String
,
AppSourceInterfaceDefinition
>
getPathToDefinitionMap
()
{
return
this
.
appSourcePathToDefinitionMap
;
}
}
src/main/java/mil/tron/commonapi/appgateway/AppSourceEndpoint.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.appgateway
;
import
lombok.Value
;
import
org.springframework.web.bind.annotation.RequestMethod
;
@Value
public
class
AppSourceEndpoint
{
String
path
;
RequestMethod
method
;
}
src/main/java/mil/tron/commonapi/appgateway/AppSourceEndpointsBuilder.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.appgateway
;
import
java.io.FileNotFoundException
;
import
java.io.IOException
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.core.io.ClassPathResource
;
import
org.springframework.core.io.Resource
;
import
org.springframework.http.MediaType
;
import
org.springframework.stereotype.Service
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.servlet.mvc.method.RequestMappingInfo
;
import
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
;
import
io.swagger.v3.oas.models.PathItem
;
import
io.swagger.v3.parser.OpenAPIV3Parser
;
import
io.swagger.v3.parser.core.models.SwaggerParseResult
;
import
lombok.extern.slf4j.Slf4j
;
import
mil.tron.commonapi.ApplicationProperties
;
import
mil.tron.commonapi.controller.AppGatewayController
;
import
mil.tron.commonapi.entity.appsource.AppEndpoint
;
import
mil.tron.commonapi.entity.appsource.AppSource
;
import
mil.tron.commonapi.repository.appsource.AppEndpointRepository
;
@Service
@Slf4j
public
class
AppSourceEndpointsBuilder
{
private
AppGatewayController
queryController
;
private
RequestMappingHandlerMapping
requestMappingHandlerMapping
;
private
AppSourceConfig
appSourceConfig
;
private
AppEndpointRepository
appEndpointRepository
;
private
ApplicationProperties
versionProperties
;
private
AppGatewayRouteBuilder
appGatewayRouteBuilder
;
@Autowired
AppSourceEndpointsBuilder
(
RequestMappingHandlerMapping
requestMappingHandlerMapping
,
AppGatewayController
queryController
,
AppSourceConfig
appSourceConfig
,
AppEndpointRepository
appEndpointRepository
,
ApplicationProperties
versionProperties
,
AppGatewayRouteBuilder
appGatewayRouteBuilder
)
{
this
.
requestMappingHandlerMapping
=
requestMappingHandlerMapping
;
this
.
queryController
=
queryController
;
this
.
appSourceConfig
=
appSourceConfig
;
this
.
versionProperties
=
versionProperties
;
this
.
appEndpointRepository
=
appEndpointRepository
;
this
.
appGatewayRouteBuilder
=
appGatewayRouteBuilder
;
this
.
createAppSourceEndpoints
(
this
.
appSourceConfig
);
}
private
void
createAppSourceEndpoints
(
AppSourceConfig
appSourceConfig
)
{
Map
<
AppSourceInterfaceDefinition
,
AppSource
>
appDefs
=
appSourceConfig
.
getAppSourceDefs
();
if
(
appDefs
.
keySet
().
size
()
==
0
)
{
log
.
warn
(
"No AppSource Definitions were found."
);
return
;
}
for
(
AppSourceInterfaceDefinition
appDef
:
appDefs
.
keySet
())
{
this
.
initializeWithAppSourceDef
(
appDef
,
appDefs
.
get
(
appDef
));
}
}
public
void
initializeWithAppSourceDef
(
AppSourceInterfaceDefinition
appDef
,
AppSource
appSource
)
{
try
{
List
<
AppSourceEndpoint
>
appSourceEndpoints
=
this
.
parseAppSourceEndpoints
(
appDef
.
getOpenApiSpecFilename
());
boolean
newMapping
=
this
.
appSourceConfig
.
addAppSourcePathToDefMapping
(
appDef
.
getAppSourcePath
(),
appDef
);
// Register Camel routes for each individual App Source
appGatewayRouteBuilder
.
createGatewayRoute
(
appDef
.
getAppSourcePath
());
if
(
newMapping
)
{
for
(
AppSourceEndpoint
appEndpoint:
appSourceEndpoints
)
{
for
(
String
prefix
:
this
.
versionProperties
.
getCombinedPrefixes
())
{
this
.
addMapping
(
appDef
.
getAppSourcePath
(),
appEndpoint
,
prefix
);
}
this
.
addEndpointToSource
(
appEndpoint
,
appSource
);
}
}
setUnusedFlagOnEndpointsNotInSpec
(
appSourceEndpoints
,
appSource
);
}
catch
(
FileNotFoundException
e
)
{
log
.
warn
(
String
.
format
(
"Endpoints for %s could not be loaded from %s. File not found."
,
appDef
.
getName
(),
appDef
.
getOpenApiSpecFilename
()),
e
);
}
catch
(
IOException
e
)
{
log
.
warn
(
String
.
format
(
"Endpoints for %s could not be loaded from %s"
,
appDef
.
getName
(),
appDef
.
getOpenApiSpecFilename
()),
e
);
}
catch
(
NoSuchMethodException
e
)
{
log
.
warn
(
"Unable to map app source path to a controller handler."
,
e
);
}
}
private
void
setUnusedFlagOnEndpointsNotInSpec
(
List
<
AppSourceEndpoint
>
appSourceEndpoints
,
AppSource
appSource
)
{
List
<
AppEndpoint
>
unusedEndpoints
=
appSource
.
getAppEndpoints
().
parallelStream
()
.
filter
(
item
->
appSourceEndpoints
.
stream
()
.
noneMatch
(
appSourceEndpoint
->
item
.
getPath
().
equals
(
appSourceEndpoint
.
getPath
())
&&
item
.
getMethod
().
equals
(
appSourceEndpoint
.
getMethod
())))
.
map
(
item
->
{
item
.
setDeleted
(
true
);
return
item
;
})
.
collect
(
Collectors
.
toList
());
appEndpointRepository
.
saveAll
(
unusedEndpoints
);
}
public
List
<
AppSourceEndpoint
>
parseAppSourceEndpoints
(
String
openApiFilename
)
throws
IOException
{
Resource
apiResource
=
new
ClassPathResource
(
"appsourceapis/"
+
openApiFilename
);
SwaggerParseResult
result
=
new
OpenAPIV3Parser
().
readLocation
(
apiResource
.
getURI
().
toString
(),
null
,
null
);
return
result
.
getOpenAPI
().
getPaths
().
entrySet
().
stream
()
.
map
(
path
->
{
String
pathString
=
path
.
getKey
();
// get operations from paths.. .readOperations
return
path
.
getValue
().
readOperationsMap
()
// build pojo for path and operations
.
keySet
().
stream
().
map
(
method
->
new
AppSourceEndpoint
(
pathString
,
AppSourceEndpointsBuilder
.
convertMethod
(
method
)))
.
collect
(
Collectors
.
toList
());
}).
flatMap
(
List:
:
stream
).
collect
(
Collectors
.
toList
());
}
public
static
RequestMethod
convertMethod
(
PathItem
.
HttpMethod
swaggerHttpMethod
)
{
RequestMethod
converted
;
switch
(
swaggerHttpMethod
)
{
case
GET:
converted
=
RequestMethod
.
GET
;
break
;
case
POST:
converted
=
RequestMethod
.
POST
;
break
;
case
PUT:
converted
=
RequestMethod
.
PUT
;
break
;
case
DELETE:
converted
=
RequestMethod
.
DELETE
;
break
;
case
PATCH:
converted
=
RequestMethod
.
PATCH
;
break
;
default
:
converted
=
RequestMethod
.
GET
;
break
;
}
return
converted
;
}
private
void
addMapping
(
String
appSourcePath
,
AppSourceEndpoint
endpoint
,
String
prefix
)
throws
NoSuchMethodException
{
RequestMappingInfo
requestMappingInfo
=
RequestMappingInfo
.
paths
(
String
.
format
(
"%s/%s%s"
,
prefix
,
appSourcePath
,
endpoint
.
getPath
()))
.
methods
(
endpoint
.
getMethod
())
.
produces
(
MediaType
.
APPLICATION_JSON_VALUE
)
.
build
();
if
(
endpoint
.
getMethod
().
equals
(
RequestMethod
.
GET
))
{
requestMappingHandlerMapping
.
registerMapping
(
requestMappingInfo
,
queryController
,
AppGatewayController
.
class
.
getDeclaredMethod
(
"handleCachedRequests"
,
HttpServletRequest
.
class
,
HttpServletResponse
.
class
,
Map
.
class
));
}
else
{
requestMappingHandlerMapping
.
registerMapping
(
requestMappingInfo
,
queryController
,
AppGatewayController
.
class
.
getDeclaredMethod
(
"handleRequests"
,
HttpServletRequest
.
class
,
HttpServletResponse
.
class
,
Map
.
class
));
}
}
private
void
addEndpointToSource
(
AppSourceEndpoint
endpoint
,
AppSource
appSource
)
{
AppEndpoint
appEndpoint
=
appEndpointRepository
.
findByAppSourceEqualsAndMethodEqualsAndPathEquals
(
appSource
,
endpoint
.
getMethod
(),
endpoint
.
getPath
())
.
orElse
(
AppEndpoint
.
builder
()
.
appSource
(
appSource
)
.
method
(
endpoint
.
getMethod
())
.
path
(
endpoint
.
getPath
())
.
build
());
appEndpoint
.
setDeleted
(
false
);
try
{
this
.
appEndpointRepository
.
save
(
appEndpoint
);
}
catch
(
Exception
e
)
{
log
.
warn
(
String
.
format
(
"Unable to add endpoint to app source %s."
,
appSource
.
getName
()),
e
);
}
}
}
src/main/java/mil/tron/commonapi/appgateway/AppSourceInterfaceDefinition.java
deleted
100644 → 0
View file @
34632cf5
package
mil.tron.commonapi.appgateway
;
import
lombok.*
;
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Builder
public
class
AppSourceInterfaceDefinition
{
String
name
;
String
openApiSpecFilename
;
String
sourceUrl
;
String
appSourcePath
;
}
Prev
1
2
3
4
5
…
14
Next